0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

C++內(nèi)存管理operator new和placement new

冬至子 ? 來源:鳴鳴鑼的小屋 ? 作者:Maxwell Luo ? 2023-07-22 09:58 ? 次閱讀

>>> 背景

最近在看一些C++資料的過程中,說到在初始化列表中使用關(guān)鍵字new來分配新內(nèi)存不是異常安全的,應(yīng)該使用運算符new。這里就引發(fā)了我對C++ new的全新認識。

class A {
public:
    A(int a) : px(new int(a)) {}  // 當然這里基礎(chǔ)類是不會異常的
    int* px;
};

>>> 內(nèi)容

首先我們來回憶一下最常規(guī)的new用法。首先創(chuàng)建一個測試類A,并在其構(gòu)造和析構(gòu)函數(shù)里面打印提示語句??梢园l(fā)現(xiàn),在new一個A對象的時候調(diào)用了構(gòu)造函數(shù),在delete一個A對象的時候析構(gòu)了此對象。而且與C標準庫中的malloc函數(shù)相比,new關(guān)鍵字不需要知道分配的字節(jié)數(shù),而是對類型大小做了自動推斷,顯然更加方便。

class A {
public:
    A(int a) : _a(a) {
        cout < < "object A(" < < _a < < ") is constructed.n";
    }
    ~A() {
        cout < < "object A(" < < _a < < ") is destructed.n";
    }
    int _a;
};


int main() {
    A* obj = new A(1);
    delete obj;


    return 0;
}
object A(1) is constructed.
object A(1) is destructed.

但是方便的代價就是隱藏了很多細節(jié),從而可能導(dǎo)致使用者在沒有充分理解的情況下造成誤用。其實關(guān)鍵字new做了非常多的操作。

這里首先給出3個概念,分別是:關(guān)鍵字new、操作符new和放置new(或者說,keywords new、operator new、placement new)。它們之間的關(guān)系大概如下所示。

圖片

當我們使用關(guān)鍵字new去創(chuàng)建一個對象時,會首先根據(jù)A類型推斷出需要申請的內(nèi)存字節(jié)數(shù),然后再交給operator new去按字節(jié)數(shù)申請一塊可用的內(nèi)存(否則拋出異常),最后調(diào)用類的構(gòu)造函數(shù)創(chuàng)造一個對象保存在申請的這段內(nèi)存中。

圖片

而placement new起到的作用是在分配好的內(nèi)存上創(chuàng)建對象,和operator new有那么一點互補的意思。placement new的引入是為了避免一些頻繁的內(nèi)存申請和回收操作,可以專門申請一塊內(nèi)存做重復(fù)的計算,而不是需要一個對象就申請一個內(nèi)存,從而提高效率。

圖片

下面是一個比較綜合的例子,來表現(xiàn)這些new之間不同??梢钥吹?,我們首先通過operator new來創(chuàng)建一塊能夠容納3個A對象的內(nèi)存空間,然后通過placement new來在這個申請好的內(nèi)存空間上創(chuàng)建對象,最后使用operator delete把申請的空間銷毀。

可以看到operator new不會調(diào)用構(gòu)造函數(shù),operator delete也不會調(diào)用析構(gòu)函數(shù)。通過placement new配合起始指針的偏移,可以逐個在新內(nèi)存上創(chuàng)建有意義的數(shù)據(jù)對象。

int main() {
    A* mempool = (A*)operator new(sizeof(A) * 3);
    cout < < "Memory is allocated!n";
    A* obj1 = new(mempool) A(1);
    A* obj2 = new(mempool + 1) A(2);
    A* obj3 = new(mempool + 2) A(3);
    cout < < obj1- >_a < < endl;
    cout < < obj2- >_a < < endl;
    cout < < obj3- >_a < < endl;
    operator delete(mempool);
    cout < < obj1- >_a < < endl;
    cout < < obj2- >_a < < endl;
    cout < < obj3- >_a < < endl;


    return 0;
}
Memory is allocated!
object A(1) is constructed.
object A(2) is constructed.
object A(3) is constructed.
1
2
3
35134640
0
1448320

>>> 小結(jié)

可以看出,C++在內(nèi)存分配引入了不少的概念,operator new和operator delete都是可以被自定義類重載的,這就給予了程序員很好的自由度。除了使用new和delete來管理內(nèi)存外,C++還引入了更為復(fù)雜的allocator(或分配器)的概念。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 分配器
    +關(guān)注

    關(guān)注

    0

    文章

    192

    瀏覽量

    25612
  • C++語言
    +關(guān)注

    關(guān)注

    0

    文章

    147

    瀏覽量

    6931
收藏 人收藏

    評論

    相關(guān)推薦

    深入C++內(nèi)存管理

    說到 C++內(nèi)存管理,我們可能會想到??臻g的本地變量、堆上通過 new 動態(tài)分配的變量以及全局命名空間的變量等,這些變量的分配位置都是由系統(tǒng)來控制
    發(fā)表于 11-12 09:29 ?550次閱讀

    New C++基礎(chǔ)與提高

    New C++基礎(chǔ)與提高-王桂林
    發(fā)表于 09-22 15:44

    請問C++new和不用new創(chuàng)建類對象區(qū)別是什么?

    起初剛學(xué)C++時,很不習(xí)慣用new,后來看老外的程序,發(fā)現(xiàn)幾乎都是使用new,想一想?yún)^(qū)別也不是太大,但是在大一點的項目設(shè)計中,有時候不使用new的確會帶來很多問題。當然這都是跟
    發(fā)表于 11-05 07:27

    A New Standard for Multiproces

    A New Stan
    發(fā)表于 09-15 10:06 ?996次閱讀
    A <b class='flag-5'>New</b> Standard for Multiproces

    placement new詳解

    placement new是重載operator new的一個標準、全局的版本,它不能被自定義的版本代替(不像普通的operator
    發(fā)表于 03-02 14:24 ?0次下載

    C++語法的外圍基礎(chǔ)

    程序?qū)?b class='flag-5'>內(nèi)存空間的動態(tài)分配的頻繁程度要求簡化語言的相關(guān)語法的格式。C++語法規(guī)定new算符等效于C語言中mal1oc一類的函數(shù)功能;free算符等效于
    發(fā)表于 03-15 16:55 ?10次下載

    了解一下比較復(fù)雜也非常神秘的new

    new”是C++的一個關(guān)鍵字,同時也是操作符。關(guān)于new的話題非常多,因為它確實比較復(fù)雜,也非常神秘。
    的頭像 發(fā)表于 04-23 15:27 ?3537次閱讀
    了解一下比較復(fù)雜也非常神秘的<b class='flag-5'>new</b>

    新英特爾C/C++編譯器16.0中C/C++語言的特點

    This talk will cover new features in Intel? C/C++ Compiler 16.0 as part of the Intel? Parallel
    的頭像 發(fā)表于 10-23 06:57 ?4121次閱讀

    C++內(nèi)存管理技術(shù)的詳細資料說明

    內(nèi)存管理C++最令人切齒痛恨的問題,也是C++最有爭議的問題,C++高手從中獲得了更好的性能,更大的自由,
    發(fā)表于 03-14 08:00 ?4次下載

    C++內(nèi)存管理詳細介紹

    引言 說到 C++內(nèi)存管理,我們可能會想到??臻g的本地變量、堆上通過 new 動態(tài)分配的變量以及全局命名空間的變量等,這些變量的分配位置都是由系統(tǒng)來控制
    的頭像 發(fā)表于 01-11 10:31 ?2618次閱讀

    如何讓new操作符不分配內(nèi)存,只構(gòu)造

    placement new 就可以解決這個問題。我們構(gòu)造對象都是在一個預(yù)先準備好了的內(nèi)存緩沖區(qū)中進行,不需要查找內(nèi)存,內(nèi)存分配的時間是常數(shù);
    的頭像 發(fā)表于 01-19 17:01 ?1923次閱讀

    new和malloc函數(shù)詳細分析底層邏輯

    new操作符從自由存儲區(qū)(free store)上為對象動態(tài)分配內(nèi)存空間,而malloc函數(shù)從堆上動態(tài)分配內(nèi)存。自由存儲區(qū)是C++基于new
    的頭像 發(fā)表于 04-03 09:29 ?626次閱讀

    嵌入式C++內(nèi)存管理的應(yīng)用程序

    說到 C++內(nèi)存管理,我們可能會想到??臻g的本地變量、堆上通過 new 動態(tài)分配的變量以及全局命名空間的變量等,這些變量的分配位置都是由系統(tǒng)來控制
    發(fā)表于 10-12 10:37 ?254次閱讀
    嵌入式<b class='flag-5'>C++</b><b class='flag-5'>內(nèi)存</b><b class='flag-5'>管理</b>的應(yīng)用程序

    new和malloc的區(qū)別

    1. 申請的內(nèi)存所在位置 new操作符從自由存儲區(qū)(free store)上為對象動態(tài)分配內(nèi)存空間,而malloc函數(shù)從堆上動態(tài)分配內(nèi)存。自由存儲區(qū)是
    的頭像 發(fā)表于 11-11 11:29 ?483次閱讀
    <b class='flag-5'>new</b>和malloc的區(qū)別

    C++內(nèi)存管理問題

    寫服務(wù)端的,內(nèi)存是一個繞不過的問題,而用C++寫的,這個問題就顯得更嚴重。進程的內(nèi)存持續(xù)上漲,有可能是正常的內(nèi)存占用,也有可能是內(nèi)存碎片,而
    的頭像 發(fā)表于 11-13 11:13 ?516次閱讀
    <b class='flag-5'>C++</b><b class='flag-5'>內(nèi)存</b><b class='flag-5'>管理</b>問題