C++ 什么';这是一个单独的;操作员新[]”;?
看起来C++ 什么';这是一个单独的;操作员新[]”;?,c++,memory-management,C++,Memory Management,看起来operator new和operator new[]具有完全相同的签名: void* operator new( size_t size ); void* operator new[]( size_t size ); 并执行完全相同的操作:要么返回一个指向足够大的原始(未以任何方式初始化)内存块的指针,要么抛出一个异常 当我使用new创建对象时,operator new也会在内部调用operator new[]——当我使用new[]创建对象数组时。以上两个特殊函数的内部调用C++完全相
operator new
和operator new[]
具有完全相同的签名:
void* operator new( size_t size );
void* operator new[]( size_t size );
并执行完全相同的操作:要么返回一个指向足够大的原始(未以任何方式初始化)内存块的指针,要么抛出一个异常
当我使用new
创建对象时,operator new
也会在内部调用operator new[]
——当我使用new[]创建对象数组时。以上两个特殊函数的内部调用C++完全相同,我不知道这两个调用的含义有什么不同。
拥有两个具有完全相同签名和行为的不同函数的目的是什么?可以覆盖运算符(对于特定类、命名空间或全局),如果希望以不同于数组分配的方式处理对象分配,则可以提供不同的版本。例如,您可能希望从不同的内存池进行分配。我已经对这一点进行了合理的研究,坦率地说,从接口的角度来看,没有任何理由
我能想到的唯一可能的原因是允许对实现进行优化提示,operator new[]
可能会被调用以分配更大的内存块;但是这是一个非常非常脆弱的假设,因为你可以new
一个非常大的结构,或者newchar[2]
它实际上算不上大
请注意,operator new[]
不会为数组计数或任何东西添加任何神奇的额外存储。new[]
操作员的工作是计算需要多少开销(如果有),并将正确的字节计数传递给操作员new[]
[使用gcc进行的测试表明,new[]
不需要额外的存储,除非正在构造的数组成员的类型有一个非平凡的析构函数。]
从界面和合同的角度(除了需要使用正确的相应解除分配功能外)operator new
和operator new[]
是相同的。一个目的是用户可以单独定义它们。因此,如果我想将单堆分配对象中的内存初始化为0xFEFE,并将堆分配数组中的内存初始化为0xEFEF,因为我认为这将有助于调试,那么我可以
那是否值得是另一回事。我想,如果您的特定程序主要使用非常小的对象和非常大的数组,那么您可以分配不同的堆,希望这样可以减少碎片。但同样地,您可以识别分配了大量数组的类,只需为这些类重写operator new[]
。或者,operator new
可以根据大小在不同堆之间切换
实际上,要求的措辞有所不同。一个为指定大小的任何对象分配对齐的内存,另一个为指定大小的任何数组分配对齐的内存。我不认为有任何区别-大小为1的数组肯定与对象具有相同的对齐方式-但我可能弄错了。默认情况下,数组版本返回的值与对象版本的值相同,这一事实强烈表明两者没有区别。或者至少一个对象上的对齐要求比数组上的更严格,我无法理解…标准说new t
调用operator new()
和new t[]
导致调用operator new[](
)。如果你想的话,你可以让它们超载。我认为默认情况下,它们之间没有区别。标准规定它们是可更换的(3.7.3/2):
该库为全局分配和解除分配函数提供默认定义。一些全球性的
分配和解除分配功能是可替换的(18.4.1)。C++程序最多应提供一个
可替换分配或解除分配函数的定义。任何此类函数定义都将替换
库中提供的默认版本(17.4.3.4)。以下是分配和解除分配函数
(18.4)在程序的每个翻译单元的全局范围内隐式声明
void* operator new(std::size_t) throw(std::bad_alloc);
void* operator new[](std::size_t) throw(std::bad_alloc);
void operator delete(void*) throw();
void operator delete[](void*) throw();
在C++的设计和演化(第10.3节)中,Stroustrup提到如果对象X的新运算符本身用于分配对象X的数组,那么X::运算符new()的编写者也必须处理数组分配,这不是新的()的常用用法,并且增加了复杂性。因此,没有考虑使用new()进行数组分配。然后,没有简单的方法为动态阵列分配不同的存储区域。解决方案是为数组提供单独的分配器和解除定位器方法:new[]和delete[]。
…尤其是当数组类型的对象仍然是一个对象时。是的,我正在考虑编辑以添加它。但是数组类型的对象不是任何对象,它是所有对象的严格子集的一部分,因此可能具有较弱的对齐要求。我不确定sizeof(T[1])>sizeof(T)
是否合法,但如果合法,那么您可以想象,在某些实现中,大小为8字节的数组的对齐要求可能只有4(因为这是最大的T),而大小为8字节的对象的对齐要求可能是8(因为存在一个8对齐类型)。我相当肯定,不允许sizeof(t[1])>sizeof(t)
,因为我记不起来了;可能是指针算术定义的问题。t[1]
的对齐可以是>sizeoft[1]
。我认为将new和array放入操作符new
分配的内存是合法的,因为数组是一个对象。哦,是的,整个数组大小