我正在阅读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
或不调用来实现。可以保证的是malloc
和free
不使用它们(因此,如果您想重新实现这些函数而没有无限递归的风险,您可以调用malloc
和free
)。
从全局命名空间调用operator new
,以防用户(或其他人)决定使用new
运算符。
双冒号用于防止调用 T::运算符 new()(如果 定义)。