Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/wordpress/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么';这是一个单独的;操作员新[]”;?_C++_Memory Management - Fatal编程技术网

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]
的对齐可以是>sizeof
t[1]
。我认为将new和array放入
操作符new
分配的内存是合法的,因为数组是一个对象。哦,是的,整个数组大小