为什么SGI STL源代码在运算符新函数前面使用双冒号



我正在阅读SGI标准模板库的源代码。我发现 operator new 函数前面总是有一个双冒号。喜欢这个:

T* tmp = (T*)(::operator new((size_t)(size * sizeof(T))));

operator new可以在不添加::字段的情况下直接调用,那么为什么 STL 编码人员会这样编写呢?如果我们不使用他们面前的::,可能会遇到什么陷阱或情况。

您可以重载类的运算符 new,并以 "::" 为它添加前缀,这将调用全局"默认"运算符 new 而不是可能的重载。例如:

#include <iostream>
class Foo
{
public:
  Foo() { std::cout << "Foo::Foo()" << std::endl; }
  void * operator new(size_t )
  { 
    std::cout << "Foo::operator new()" << std::endl; 
    return static_cast<Foo *>(malloc(sizeof(Foo)));
  }
};

int main()
{
  Foo foo;
  std::cout << "----------------------" << std::endl;
  Foo * p = new Foo;
  std::cout << "----------------------" << std::endl;
  Foo * q = ::new Foo;
}

将打印

Foo::Foo()
----------------------
Foo::operator new()
Foo::Foo()
----------------------
Foo::Foo()

编辑:截取的代码确实在类作用域中定义的运算符 new 无关。一个更好的例子是:

#include <iostream>
namespace quux {
void * operator new(size_t s)
{
  std::cout << "quux::operator new" << std::endl;
  return malloc(s);
}
void foo()
{
  std::cout << "quux::foo()" << std::endl;
  int * p = static_cast<int*>(operator new(sizeof(int)));
}
void bar()
{
  std::cout << "quux::bar()" << std::endl;
  int * p = static_cast<int*>(::operator new(sizeof(int)));
}
} // namespace quux

int main()
{
  quux::foo();
  quux::bar();
}

哪些打印

quux::foo()
quux::operator new
quux::bar()

C++ 中的::operator new是全局内存分配器,每次单个对象需要一定数量的字节时都会调用它。请注意,返回值是一个void *::operator new(size_t)处理原始字节,而不是对象。

它基本上是malloc C++对应的,只是一个有趣的名字。

而是使用单独的全局分配器::operator new[](size_t sz)为对象数组分配内存。

这两个运算符(它们的对应运算符 ::operator delete::operator delete[] 以及分配器的nothrow版本)用于满足C++运行时的所有内存需求。

它们可以通过调用malloc/free或不调用来实现。可以保证的是mallocfree不使用它们(因此,如果您想重新实现这些函数而没有无限递归的风险,您可以调用mallocfree)。

从全局命名空间调用operator new,以防用户(或其他人)决定使用new运算符。

双冒号用于防止调用 T::运算符 new()(如果 定义)。

最新更新