"::operator new"和"::operator delete"是什么?

14

我知道newdelete是关键字。

int obj = new int;
delete obj;

int* arr = new int[1024];
delete[] arr;

<new>头文件是C++标准头文件的一部分。它有两个运算符(我不确定它们是运算符还是函数):

::operator new

::operator delete

这些运算符可以像下面这样使用:

#include <new>
using namespace std;

int* buff = (int*)::operator new(1024 * sizeof(int));
::operator delete(buff);

::operator new和::operator delete是C++中的全局函数,用于动态分配内存。它们与newdelete关键字不同,后者是具有特定语法的表达式。

4个回答

23

使用单独的new关键字和operator new函数并不相同。

调用:

Object* p = new Object(value);

等同于调用

void* v = operator new(sizeof(Object));
p = reinterpret_cast<Object*>(v);
p->Object::Object(value); //this is not legal C++, it just represent the implementation effect

操作符new(或更好地说是void* operator new(size_t)变体)只分配内存,但不执行任何对象构造。

new关键字调用operator new函数,然后调用对象构造函数。

为了将内存分配与对象构造分离,声明了operator new的一种变体。

void* operator new(size_t, void* at)
{ return at; }

前面的代码通常是这样写的:

Object* p = reinterpret_cast<Object*>(operator new(sizeof(Object))); //no contruction here
new(p) Object(value); //calls operator new(size_t, void*) via keyword

operator new(size_t, void*) 在本身并没有实际作用,但是通过这个关键字调用会导致构造函数被调用。

相反地,析构和释放可以分开进行。

p->~Object();
operator delete(p); //no destructor called

使用operator delete(void*)代替delete p;前者会先调用析构函数,然后再调用operator delete(void*)


12

:: 告诉编译器调用全局命名空间中定义的运算符。
它是全局 newdelete 运算符的完全合格名称。

请注意,可以替换全局 newdelete 运算符以及重载类特定的 newdelete 运算符。因此,在程序中可能会有两个版本的 newdelete 运算符。使用作用域解析运算符的完全合格名称告诉编译器您正在引用全局版本的运算符而不是类特定的运算符。


1
但程序员应该包括 new 头文件。 - Amir Saniyan
2
@AmirSaniyan 如果你想使用定位new,那么包含新头文件的唯一原因(我所知道的)就是这个。 - Benj
@AmirSaniyan:好文章:C++中何时需要#include <new>库? - Alok Save
正如Benj所说:如果您正在使用标准的放置new之一。或者如果您需要访问std :: bad_alloc或头文件中声明的其他少数函数。无论您只是编写 new MyType 还是 :: new MyType,标准非放置new都不需要它,并且如果您的 new 表达式解析为用户定义的 operator new,而不是标准库中的一个,则不需要它。 - James Kanze
@JamesKanze:没错,我已经在评论中链接了相关的问题。那里有一个答案(不是被采纳的那个),非常恰当地解决了这个问题。 - Alok Save

6
它们是分配器和释放器函数。 new 运算符执行两个操作:它调用分配器函数以获取内存,并调用对象的构造函数。 delete 运算符也执行两个操作:它调用对象的析构函数,然后调用释放器函数。默认分配器函数是 :: operator new,默认释放器函数是 :: operator delete。 用户可以替换这两个函数。
请注意,在新的表达式中,::operator new 函数的查找方式与在成员函数内部调用普通函数时几乎相同。就像普通函数一样,您可以限定运算符来更改查找方式:如果存在,则 new MyClass 将查找成员 operator new::new MyClass 将使用默认分配器,即使 MyClass 定义了成员 operator new

+1 是为了区分分配函数和 new-expression。它们在语法上都使用 new 关键字。 - Steve Jessop

3

:: 表示全局命名空间。


new是一个关键字时,为什么我应该使用全局命名空间? - Amir Saniyan
1
你不应该这样做,因为它显示你正在使用全局命名空间的新版本。但是,你可以重写你的新版本,然后在需要时使用你的命名空间。 - Denis Ermolin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接