谁定义了新的运营商?

Who defines the new operator?

这个程序可以编译吗?

int main(){
    double* p = new double[4];
    delete[] p;
    return 0;
}

(使用 GCC 7.1.1 编译)

我问这个的原因是,我不确定是谁提供了 operator new 的定义。 是语言吗?编译器默认是 #includeing <new>?

为了让这个问题更清楚,我实际上可以定义(覆盖?)运算符 new.

#include<cstdlib> // malloc and size_t
#include<cassert> // assert
void* operator new[](unsigned long int sz){ // what if this is not defined? who provides `new`?
    assert(0); // just to check I am calling this function
    return std::malloc(sz);
}
int main(){
    double* p = new double[4]; // calls the new function above
    delete[] p;
    return 0;
}

我在这里做什么?

覆盖new?超载 newnew 的定义对编译器来说是特殊的(魔法)吗? (例如,如果未定义,则使用提供的语言)。 #include<new> 在这一切中的作用是什么?

这里有一个 new 表达式,它确实调用了 operator new[]

void* operator new[]( std::size_t count );

编译器在每个翻译单元中隐式声明基本 operator news(这是由标准指定的),请参阅 cppreference documentation.

The versions (1-4) are implicitly declared in each translation unit even if the < new> header is not included.

在你的第二个代码片段中,你重载(技术上你实际上是替换operator new(不是overriding,这只适用于虚函数),尽管你应该重载 operator new[](注意,如果你不这样做,那么 operator new[] 将退回到 operator new],所以从技术上讲,我相信您的代码没问题,但为了清楚起见,我只是重载了数组版本)。

operator new 可以有其他重载。您拥有由编译器提供的标量和数组版本,可能由标准库提供,也可能由用户代码提供。

如果您自己编写(如果它们没有内置版本的签名)或者如果您#include new,则会有额外的 new(和 delete)重载。如果您提供与内置签名匹配的运算符,那么它们将替换内置版本。谨防。 :)

人们加入的主要原因是

1) 在用户提供的内存地址中构造对象

2) new

的非抛出版本

当然,还有运算符删除重载,因为 new/delete 必须成对重载才能一起工作,否则几乎肯定会发生破坏。如果您的 operator new 与内置签名匹配,它将替换而不是重载内置版本。

记住,一个 "new expression" 就像:

std::string myString = new std::string();

实际上分为两部分:1) 分配内存(通过 operator new),然后 2) 在该内存中构造一个对象。如果成功,它 return 是指向该对象的指针,如果失败,则清除构造的内容,释放已分配的内容,然后抛出。

当你重载operator new时,你只是在处理内存分配,而不是构造函数调用,对象将在这个operator return的任何地址构造。对于正常的 placement new,你可能会看到这样的代码:

char myBuffer[1024];  // assume aligned; nobody needs more than 1024 bytes
std::string *ptr = new (myBuffer) std::string();
assert (ptr == &myBuffer);

new 的额外参数是 myBuffer 地址,它立即被 operator new returned 并成为构造对象的地方。断言应该通过,并显示字符串是在 myBuffer.

的字节中创建的

在#including new 之后也可以使用 new 的无抛出版本,它还使用了一个额外的运算符参数:

char * buf = new (std::nothrow) char[MAX_INT];
if (buf) {
    std::cout << "WHOA, you have a lot of memory!!!\n";
}

现在它不会失败,而是 return 一个空指针,所以你必须检查它。