除了分配内存和调用构造函数之外,
new
运算符还有哪些其他作用?<new>
头文件中常用的 new 运算符的单个对象形式有如下规定:
C++标准还有很多其他关于 new 运算符和动态内存分配的内容(非常多),但我认为“默认行为”列表很好地概括了 new 运算符的基本知识。行为要求:
返回一个指向适当对齐存储器(3.7.3)的非空指针,否则引发 bad_alloc 异常。此要求对该函数的替换版本具有约束力。
默认行为:
— 执行循环:在循环内部,该函数首先尝试分配请求的存储器。尝试是否涉及调用标准 C 库函数 malloc 是未指定的。
— 如果尝试成功,则返回指向已分配存储器的指针。否则,如果 set_new_handler() 的最后一个参数是空指针,则抛出 bad_alloc 异常。
— 否则,该函数调用当前的 new_handler (18.4.2.2)。如果被调用的函数返回,则重复循环。
— 当分配请求的存储器尝试成功或被调用的 new_handler 函数不返回时,该循环终止。
new
获得内存new
处理内存失败new
处理构造函数异常new
处理特殊放置和nothrow版本free
的大小(::operator new只需使用malloc
):void * memory = malloc(x);
free (memory); // no need to tell it the size
这里有一个例子,可以看到存储大小对于新表达式的数组形式的分配大小有影响(不在我的其他答案中涉及):
#include <cstddef>
#include <iostream>
struct f {
// requests allocation of t bytes
void * operator new[](std::size_t t) throw() {
void *p = ::operator new[](t);
std::cout << "new p: " << p << std::endl;
std::cout << "new size: " << t << std::endl;
return p;
}
// requests deleting of t bytes starting at p
void operator delete[](void *p, std::size_t t) throw() {
std::cout << "delete p: " << p << std::endl;
std::cout << "size : " << t << std::endl;
return ::operator delete[](p);
}
};
int main() {
std::cout << "sizeof f: " << sizeof (f) << std::endl;
f * f_ = new f[1];
std::cout << "&f_ : " << f_ << std::endl;
delete[] f_;
}
sizeof f: 1
new p: 0x93fe008
new size: 5
&f_ : 0x93fe00c
delete p: 0x93fe008
size : 5
一个字节用于对象本身,还有4个字节用于存储在对象分配区域之前的计数。如果我们使用没有大小参数的dealloc函数(只需从operator delete中删除它),我们将得到以下输出:
sizeof f: 1
new p: 0x9451008
new size: 1
&f_ : 0x9451008
delete p: 0x9451008
这里的C++运行时不再关心大小,因此不再存储它。请注意,这高度依赖于具体实现,这就是gcc在这里执行的操作,以便能够在成员operator delete中告诉您大小。其他实现可能仍然会存储大小,并且如果有类的析构函数需要调用,则很可能会存储大小。例如,只需在上面添加~f() { }
就可以使gcc存储大小,而不管我们编写了哪个释放函数。
operator delete[]
和大小的语法吗?也就是说,你能帮我看看 https://dev59.com/CkzSa4cB1Zd3GeqPkCyc 吗?谢谢! - Tobias这取决于它是否被重载,如果您为调试构建了应用程序,如果您正在使用内存泄漏检测器,如果您有某种内存池方案,如果您有像Boehm垃圾收集器之类的东西来标记/取消标记位等等。它可能在内部执行很多自定义操作,或者根本没有特殊操作。