簡體   English   中英

為什么:: operator new就足夠了,為什么:: operator new []是必要的?

[英]Why is ::operator new[] necessary when ::operator new is enough?

眾所周知,C ++標准定義了兩種形式的全局分配函數:

void* operator new(size_t);
void* operator new[](size_t);

而且,C ++標准草案(18.6.1.2 n3797)指出:

227)注意數組的重復計數或元素大小不是操作員new或操作員刪除的直接責任。 這些操作在數組new和delete表達式中的其他位置執行。 但是,數組new表達式可能會增加new運算符的size參數,以獲取存儲補充信息的空間。

讓我感到困惑的是:

如果我們刪除void* operator new[](size_t);怎么void* operator new[](size_t); 從標准,並且只是使用void* operator new(size_t)代替? 定義冗余全局分配函數的理由是什么?

我認為::operator new[]對於相當專業的系統可能很有用,在該系統中,“大而少”的數組可能由與“小而眾”的對象不同的分配器分配。 但是,目前它是遺物。

operator new可以合理地期望將在返回的確切地址處構造一個對象,而operator new[]則不能。 分配塊的第一個字節可能用於大小“ cookie”,數組可能被稀疏初始化,等等。這種區別對於成員operator new變得更有意義,后者可能專用於其特定類。

無論如何, ::operator new[]並不是必不可少的,因為std::vector (通過std::allocator )是當前最常用的獲取動態數組的方式,它會忽略它。

在現代C ++中,自定義分配器通常比自定義operator new更好。 實際上,應該完全避免使用支持容器(或智能指針等)類的new表達式,因為此類提供了更多的異常安全性。

該標准(n3936)清楚地表明這兩個運算符服務於不同但相關的目的。

operator new調用函數void* operator new(std::size_t) 第一個參數必須與運算符的參數相同。 它返回一個適當對齊的存儲塊,它可能比所需的存儲塊大一些。

operator new[]調用函數void* operator new[](std::size_t) 第一個參數可能大於提供給運算符的參數,以在數組索引需要時提供額外的存儲空間。 兩者的默認實現都是簡單地調用malloc()。

operator new[]的目的是支持特殊的數組索引(如果有)。 它與內存池或其他無關。 在利用此功能的合規實現中,該實現將在額外的空間中建立專用表,並且編譯器將為使用這些表的庫函數支持例程的指令或調用生成代碼。 在這些平台上,使用數組且未使用new []的C ++代碼將失敗。

我個人不知道有任何這樣的實現,但是它類似於某些大型機(CDC,IBM等)的支持所需的功能,這些大型機的架構與我們熟知和熱愛的Intel或RISC芯片完全不同。

我認為,已接受的答案是錯誤的。


僅出於完整性考慮,該標准(主要在S5.3.4中為n3936)包含以下內容。

  1. 分配“數組對象”或“非數組對象”之間的區別
  2. 引用“數組分配開銷”,暗示可能需要額外的存儲,並且可能(以某種方式)將其用於重復計數或元素大小。

沒有引用內存池,也沒有任何暗示可能要考慮的提示。

::operator new[]delete[]有助於內存使用調試,這是審核分配和釋放操作的中心點; 然后,您可以確保將數組形式同時使用或不使用。

如果非常不尋常/粗暴的調校用途,也有很多合理的理由:

  • 從一個單獨的池中分配數組,可能是因為這極大地提高了小型單對象動態分配對象的平均緩存命中率,

  • 數組/非數組數據的不同內存訪問提示(ala madvise

所有這些都有些奇怪,超出了99.999%的程序員的日常關注范圍,但是為什么要阻止這種可能性呢?

我敢肯定有適當的用例,需要用到單獨的new[]new ,但是我還沒有遇到用這種分離唯一可以實現的用例。

但是,我的看法是這樣的:由於用戶調用了不同版本的運算符new ,因此,如果C ++標准只定義了一個operator new ,並且其中既有new又有new[]那么它們就會故意肆意丟失信息。 這里(字面上)有一點信息, 可能某人有用,而且我認為委員會中的人們不會出於良心拋棄它!

此外,必須實施額外的new[]對我們其他人來說是一個非常小的不便之處,因此,保留一點信息的權衡取舍於必須在一小部分內實現一個簡單功能我們的程序。

C ++編程語言:特殊版 p 423說

_ operator new()operator delete()函數允許用戶接管各個對象的分配和釋放; operator new[]()operator delete[]()在數組的分配和釋放中的作用完全相同。

感謝Tony D糾正了我對此細微差別的誤解。

哇,我不太確定會使用C ++上的某些東西-我肯定在Objective-C上花了太多時間!

原來的錯誤答案

很簡單-new []表單在經典C數組的每個元素上調用構造函數

因此,它首先為所有對象分配空間,然后迭代為每個插槽調用構造函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM