谁定义了新的运营商?
Who defines the new operator?
这个程序可以编译吗?
int main(){
double* p = new double[4];
delete[] p;
return 0;
}
(使用 GCC 7.1.1 编译)
我问这个的原因是,我不确定是谁提供了 operator new
的定义。
是语言吗?编译器默认是 #include
ing <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
?超载 new
? new
的定义对编译器来说是特殊的(魔法)吗? (例如,如果未定义,则使用提供的语言)。
#include<new>
在这一切中的作用是什么?
这里有一个 new
表达式,它确实调用了 operator new[]
void* operator new[]( std::size_t count );
编译器在每个翻译单元中隐式声明基本 operator new
s(这是由标准指定的),请参阅 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 一个空指针,所以你必须检查它。
这个程序可以编译吗?
int main(){
double* p = new double[4];
delete[] p;
return 0;
}
(使用 GCC 7.1.1 编译)
我问这个的原因是,我不确定是谁提供了 operator new
的定义。
是语言吗?编译器默认是 #include
ing <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
?超载 new
? new
的定义对编译器来说是特殊的(魔法)吗? (例如,如果未定义,则使用提供的语言)。
#include<new>
在这一切中的作用是什么?
这里有一个 new
表达式,它确实调用了 operator new[]
void* operator new[]( std::size_t count );
编译器在每个翻译单元中隐式声明基本 operator new
s(这是由标准指定的),请参阅 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 一个空指针,所以你必须检查它。