C++之auto_ptr


C++之auto_ptr】 

std::auto_ptr

std::auto_ptr 屬於 STL,當然在 namespace std 中,包含頭文件 #include<memory> 便可以使用。std::auto_ptr 能夠方便的管理單個堆內存對象。

我們從代碼開始分析:

void TestAutoPtr() {

std::auto_ptr<Simple> my_memory(new Simple(1));   // 創建對象,輸出:Simple:1

if (my_memory.get()) {                            // 判斷智能指針是否為空

my_memory->PrintSomething();                    // 使用 operator-> 調用智能指針對象中的函數

my_memory.get()->info_extend = "Addition";      // 使用 get() 返回裸指針,然后給內部對象賦值

my_memory->PrintSomething();                    // 再次打印,表明上述賦值成功

(*my_memory).info_extend += " other";           // 使用 operator* 返回智能指針內部對象,然后用“.”調用智能指針對象中的函數

my_memory->PrintSomething();                    // 再次打印,表明上述賦值成功

  }

}                                                   // my_memory 棧對象即將結束生命期,析構堆對象 Simple(1)

執行結果為:

Simple: 1

PrintSomething:

PrintSomething: Addition

PrintSomething: Addition other

~Simple: 1

上述為正常使用 std::auto_ptr 的代碼,一切似乎都良好,無論如何不用我們顯示使用該死的 delete 了。

 

其實好景不長,我們看看如下的另一個例子:

void TestAutoPtr2() {

  std::auto_ptr<Simple> my_memory(new Simple(1));

  if (my_memory.get()) {

    std::auto_ptr<Simple> my_memory2;   // 創建一個新的 my_memory2 對象

    my_memory2 = my_memory;             // 復制舊的 my_memory 給 my_memory2

    my_memory2->PrintSomething();       // 輸出信息,復制成功

    my_memory->PrintSomething();        // 崩潰

  }

}

最終如上代碼導致崩潰,如上代碼時絕對符合 C++ 編程思想的,居然崩潰了,跟進 std::auto_ptr 的源碼后,我們看到,罪魁禍首是“my_memory2 = my_memory”,這行代碼,my_memory2 完全奪取了 my_memory 的內存管理所有權,導致 my_memory 懸空,最后使用時導致崩潰。

所以,使用 std::auto_ptr 時,絕對不能使用“operator=”操作符。作為一個庫,不允許用戶使用,確沒有明確拒絕[1],多少會覺得有點出乎預料。

 

看完 std::auto_ptr 好景不長的第一個例子后,讓我們再來看一個:

void TestAutoPtr3() {

  std::auto_ptr<Simple> my_memory(new Simple(1));

 

  if (my_memory.get()) {

    my_memory.release();

  }

}

執行結果為:

Simple: 1

看到什么異常了嗎?我們創建出來的對象沒有被析構,沒有輸出“~Simple: 1”,導致內存泄露。當我們不想讓 my_memory 繼續生存下去,我們調用 release() 函數釋放內存,結果卻導致內存泄露(在內存受限系統中,如果my_memory占用太多內存,我們會考慮在使用完成后,立刻歸還,而不是等到 my_memory 結束生命期后才歸還)。

正確的代碼應該為:

void TestAutoPtr3() {

  std::auto_ptr<Simple> my_memory(new Simple(1));

  if (my_memory.get()) {

    Simple* temp_memory = my_memory.release();

    delete temp_memory;

  }

}

void TestAutoPtr3() {

  std::auto_ptr<Simple> my_memory(new Simple(1));

  if (my_memory.get()) {

    my_memory.reset();  // 釋放 my_memory 內部管理的內存

  }

}

原來 std::auto_ptr 的 release() 函數只是讓出內存所有權,這顯然也不符合 C++ 編程思想。

總結:std::auto_ptr 可用來管理單個對象的對內存,但是,請注意如下幾點:

(1)    盡量不要使用“operator=”。如果使用了,請不要再使用先前對象。

(2)    記住 release() 函數不會釋放對象,僅僅歸還所有權。

(3)    std::auto_ptr 最好不要當成參數傳遞(讀者可以自行寫代碼確定為什么不能)。

(4)    由於 std::auto_ptr 的“operator=”問題,有其管理的對象不能放入 std::vector 等容器中。

(5)    ……

使用一個 std::auto_ptr 的限制還真多,還不能用來管理堆內存數組,這應該是你目前在想的事情吧,我也覺得限制挺多的,哪天一個不小心,就導致問題了。

由於 std::auto_ptr 引發了諸多問題,一些設計並不是非常符合 C++ 編程思想,所以引發了下面 boost 的智能指針,boost 智能指針可以解決如上問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM