我正在阅读SGI标准模板库的源代码。我发现operator new
函数前面总是有一个双冒号。像这样:
T* tmp = (T*)(::operator new((size_t)(size * sizeof(T))));
可以在不添加operator new
字段的情况下直接调用 ::
,那么为什么stl编码器会以这种方式编写它?如果我们不在他们面前使用::
,可能会遇到什么陷阱或情况。
答案 0 :(得分:9)
您可以为类重载operator new,并为其添加前缀“::”将调用全局“default”运算符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()
编辑:剪切的代码确实不关于在类范围中定义的operator 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()
答案 1 :(得分:1)
::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
)。
答案 2 :(得分:0)
双冒号用于防止调用T :: operator new()(如果 定义的)。
答案 3 :(得分:0)
要从全局命名空间调用operator new
,以防用户(或其他人)决定拥有new
运算符。