2014-07-16 41 views
0

我不明白爲什麼explicit shared_ptr(pointer p);不能保護開發人員不將p分配給另一個shared_ptr兩個std :: shared_ptr來自同一個原始指針

我的想法是在這裏:

#include <iostream> 
#include <memory> 

template <typename T> 
class ptr 
{ 
    public: 
     // ctor a) for lvalues 
     explicit ptr(T*& value) : value_(value) { value=nullptr; } 

     // ctor b) for rvalues pointer reference 
     explicit ptr(T*&& value) : value_(value) { } 

     ~ptr() { delete value_; } 

     // for simplicity this is left public 
     T* value_; 
}; 


int main(int argc, char *rgv[]) 
{ 
     { 
     printf("%10s | %10s | %10s\n", "raw", "p0", "p1"); 
     // create a raw pointer 
     // BAD practice but still could happen 
     int* raw = new int(1); 
     printf("%10x | %10x | %10x\n", raw, 0, 0); 

     // init p0 from raw pointer ctor (a) 
     ptr<int> p0(raw); 
     printf("%10x | %10x | %10x\n", raw, p0.value_, 0); 

     // init p1 from the same raw poiter again ctor (a) 
     ptr<int> p1(raw); 
     printf("%10x | %10x | %10x\n", raw, p0.value_, 0); 

     // nothing bad happens val was set to nullptr 
     // before p1 construction 
     } 

    // in order to construct ptr from rvalues 
    // we use ctor (b) 
    ptr<int> p2(new int()); 

     { 
     printf("\n"); 
     // create a raw pointer 
     int* raw = new int(1); 
     printf("%10x | %10x | %10x\n", raw, 0, 0); 

     // init p0 from raw pointer 
     std::unique_ptr<int> p0(raw); 
     printf("%10x | %10x | %10x\n", raw, p0.get(), 0); 

     // init "accidentally" p1 from the same raw poiter again 
     std::unique_ptr<int> p1(raw); 
     printf("%10x | %10x | %10x\n", raw, p0.get(), 0); 

     // CRASH: double free or corruption 
     } 

    return 0; 
} 

鑑於上面的代碼我有兩個問題:

1)我錯過了實現PTR這樣的任何一點:總之有什麼抓 我做沒有看到關於ptr(T*& value)ptr(T*&& value)構造器?

2)STL決定背後的原理是什麼,不要避免這個可能的bug使原始指針在shared_ptr構造中不被觸及?

+4

保護是毫無意義的;考慮:'int * raw = new int(1); int * raw2 = raw; ptr p0(raw),p1(raw2);' – Erbureth

+1

讓雙重刪除bug在雙重刪除時崩潰程序可能會更好,而不是隱藏它,並可能導致後面的空指針解引用。 –

+0

說實話,我不確定哪個更好。這樣可以更容易地追蹤錯誤回到原因,即一些破壞的shared_ptr初始化?雙刪除,發生在一個組中* some * shared_ptr的銷燬;或間接通過null,這發生在第一次使用*一個* shared_ptr有問題?我更喜歡通過堅持'make_shared'來完全消除問題,並且沒有指針在任何地方鬆動。 –

回答

2

我有沒有想過這樣實現ptr的任何一點?

如果一個類型的轉換必須被施加到指針,例如

struct Base {/*...*/}; 
struct Derived : Base {/*...*/}; 

Derived * d = new Derived; 
ptr<Base> p(d); 

然後臨時Base指針將被傳遞到右值構造,和d將被單獨留下。 (你可能會用模板構造函數繞過這個,但是可能會有更多的細節)。

當然,如果用戶愚蠢到只能保持一個原始指針,他可能是愚蠢的,以保持兩個。這個計劃只會使其中一個失效。

STL決定的基本原理是什麼?避免這種可能的bug使原始指針在shared_ptr構造中保持不變?

大概是最不驚奇的原則。

像這樣的錯誤可以通過區分智能指針和原始指針來避免,並且始終將原始指針視爲它們的危險野獸。像這樣的局部安全網只是使得難以發現等待咬住你的細微邊緣情況。使用智能指針可以避免原始指針,除非在特殊情況下(特別小心),完全消除了所有權相關錯誤的可能性。

在C++ 14,std::make_unique(除std::make_shared我們已經擁有)將意味着沒有必要爲new出現在你的代碼在所有的,使得它直白地避免這種錯誤的任何possiblilty。

相關問題