2011-01-20 65 views
1

可以說我有一個多態類結構類似的通smart_pointer來構造VS原始指針

class Base 
{ 
//some implementation 
}; 

class Deriv: public Base 
{ 
//implementation 
} 

class Case1 
{ 
    boost::scoped_ptr<A> a_ //polymorphic data member owned by C 
public: 
    Case1(A* a):a_(a) 
    { 

    } 
}; 
class Case2 
{ 
    boost::scoped_ptr<A> a_ //polymorphic data member owned by C 
public: 
    Case2(std::auto_ptr<A> a):a_(a.release()) 
    { 

    } 
}; 

而且我有一個三等功案例1/2擁有上述這些多態對象之一。現在我需要將一個指向Base/Deriv對象的指針傳遞給case1/2類的構造函數,該類取得了該對象的所有權。我是否應該將此對象作爲智能指針傳遞給auto_ptr的,使之清楚,我要拿回這個對象的照顧,或允許原始指針(案例1)允許一個更簡單的語法像

Case1 c(new Deriv); 
//compared to 
Case2 c(std::auto_ptr<Base>(new Deriv)); 

回答

3

你需要通過一個智能指針,你需要命名智能指針(例如,它不能是暫時的):

std::auto_ptr<Base> p(new Deriv); 
Case2 c(p); // this constructor would need to take the `auto_ptr` by reference 
      // so that it can steal ownership. 

在你的第一個例子,Case1 c(new Deriv);,如果一個例外是當new Deriv被執行,當Case1對象佔用的所有權之間拋出的對象可能會被泄露它在它的構造函數中。

在第二個示例中,如果您沒有命名智能指針,則在某些情況下可能會泄漏該對象。值得注意的是,這可能發生在if you have more than one argument to a function

+0

你的意思是在中間發生的完全零代碼?我也不明白爲什麼它不能是暫時的。 – Puppy 2011-01-20 21:16:23

+0

@DeadMG:零碼在哪裏?如果`Case1`構造函數在將原始指針參數分配給智能指針之前做了任何可能會引發異常的事件,則該對象將被泄漏。我已經添加了一個關於Herb Sutter的GOTW文章的鏈接。如果構造函數只有一個參數,這不是問題,但即便如此,大多數良好的編碼風格(包括Boost指南)都建議爲此指定所有智能指針。 – 2011-01-20 21:17:04

0

如果你的類完全擁有傳遞給它的對象,那麼你最好在所有適用的情況下通過使用auto_ptr來明確這一點。不得不顯式構造auto_ptr是最好的情況,因爲它強制API用戶知道你擁有該對象並減少所有權混淆的可能性。

如果你的類擁有變量所有權,那麼通常它的做法是提供一個原始指針和一個銷燬函數。

class best_practices { 
    std::function<void(A*)> destructor; 
    A* ptr; 
public: 
    best_practices(A* a, std::function<void(A*)> destructfunc) 
     : ptr(a), destructor(destructfunc) {} 
    ~best_practices() { 
     destructor(ptr); 
    } 
}; 
0

我沒有這個是一個最佳實踐的來源,但一般來說,如果你要的資源存儲在某種程度上,我覺得這是最好的收購同樣的方式,資源。

這樣做的原因是,在C++ 0x中,複製/移動是當給定參數做了,那麼你只需將它移動到存儲,如:

struct store_string 
{ 
    store_string(std::string s) : // potentially free, copy if not 
    s(std::move(s)) // free 
    {} 

    std::string s; 
}; 

還是在C + +03,如果你喜歡的類型可以廉價默認構造:所以你

struct store_string 
{ 
    store_string(std::string ss) // make necessary copy 
    { 
     s.swap(ss); // free 
    } 

    std::string s; 
}; 

,我會做:

class Case2 
{ 
    boost::scoped_ptr<A> a_ //polymorphic data member owned by C 
public: 
    Case2(boost::scoped_ptr<A>& aa) 
    { 
     a.swap(aa); // take resource 
    } 
}; 

這使得日這對你來說很簡單,並讓客戶確切知道資源將如何管理。