2010-01-27 76 views
17

關於使用shared_ptr的最佳實踐,我幾乎沒有問題。有關shared_ptr用法的問題 - C++

問題1

正在複製shared_ptr便宜?或者我需要將它作爲參考傳遞給我自己的幫助器函數並返回值?喜歡的東西,

void init_fields(boost::shared_ptr<foo>& /*p_foo*/); 
void init_other_fields(boost::shared_ptr<foo>& /*p_foo*/); 

boost::shared_ptr<foo> create_foo() 
{ 
    boost::shared_ptr<foo> p_foo(new foo); 
    init_fields(p_foo); 
    init_other_fields(p_foo); 
} 

問題2

我應該使用boost::make_shared構建一個shared_ptr?如果是的話,它提供了什麼優勢?當T沒有無參數構造函數時,我們如何使用make_shared

問題3

如何使用const foo*?我發現了兩種做法。

void take_const_foo(const foo* pfoo) 
{ 

} 

int main() 
{ 
    boost::shared_ptr<foo> pfoo(new foo); 
    take_const_foo(pfoo.get()); 
    return 0; 
} 

OR

typedef boost::shared_ptr<foo> p_foo; 
typedef const boost::shared_ptr<const foo> const_p_foo; 

void take_const_foo(const_p_foo pfoo) 
{ 

} 

int main() 
{ 
    boost::shared_ptr<foo> pfoo(new foo); 
    take_const_foo(pfoo); 
    return 0; 
} 

問題4

我怎樣才能返回,並檢查NULL一個shared_ptr對象?是這樣的,

boost::shared_ptr<foo> get_foo() 
{ 
    boost::shared_ptr<foo> null_foo; 
    return null_foo; 
} 

int main() 
{ 
    boost::shared_ptr<foo> f = get_foo(); 
    if(f == NULL) 
    { 
      /* .. */ 
    } 
    return 0; 
} 

任何幫助將是偉大的。

+2

的文檔具有定時頁:http://www.boost.org/doc/libs/1_41_0/libs/smart_ptr/smarttests.htm – 2010-01-27 05:55:06

回答

8

大部分的問題都得到了回答,但我不同意shared_ptr拷貝便宜。

副本有不同的語義從傳遞引用。它將修改引用計數,在最好的情況下會觸發原子增量,在最壞的情況下會引發鎖定。 你必須決定你需要什麼語義,然後你會知道是通過引用還是按值傳遞。

從性能角度來看,使用boost指針容器而不是shared_ptr容器通常是一個更好的主意。

+0

是的,你說得對,複製計數指針可能很貴! +1 – sbi 2010-01-28 15:43:20

2
  1. shared_ptr存在的一個基本原因是複製相對便宜。
  2. 有一些make_shared版本需要參數(如果您的編譯器支持可變參數模板,則需要一個可變參數列表)。
  3. 這聽起來像你正在尋找const_ptr_cast?
  4. 要返回空指針,可以將'0'傳遞給share_ptr ctor。要檢查空指針,可以將p.get()與0.
+7

RE#4:不'如果(F)' /'if(!f)'工作? – sbi 2010-01-27 06:19:45

+0

for#4:你可以比較'p'和0以及 – laura 2010-01-27 11:00:32

+0

@sbi和laura:是的,它的確有內置的轉換,所以大多數時候你可以把它看作是一個普通的指針。 – 2010-01-27 13:57:41

3
  1. 是的,副本是絕對便宜的。除了持有指針之外,還有(通常情況下)shared_ptr類的其他數據成員 - 使用計數。
  2. 不能回答這個問題,我一般用make_shared介紹(1.40?)
  3. 使用升壓前升壓版本:: const_pointer_cast
  4. 的shared_ptr有運營商== /!=定義。在你上面的例子:如果(F)
4
  1. 複製便宜,指針並不需要太多的空間。整個過程的重點在於使其小到允許按價值使用容器(例如std::vector< shared_ptr<Foo> >)。

  2. make_shared需要可變數量的參數,並且是您自己構建它的首選mechanicsm(就像make_pair)。其優點是可讀性,特別是如果通過臨時對象和/或命名空間涉及:

  3. boost::const_ptr_cast如已經建議

  4. 智能指針已經重載操作,並且可以在評價爲bool表達式可直接使用。請勿使用get。爲了任何東西。相反,比較p.get到任何東西的,比較一個空指針實例(my_ptr != boost::shared_ptr<MyClass>()

AD.2

func_shared(boost::shared_ptr<my_tools::MyLongNamedClass>( 
    new my_tools::MyLongNamedClass(param1, param2)); 

func_shared(boost::make_shared<my_tools::MyLongNamedClass>(param1, param2)); 
+0

'make_shared'的最大*優點不是可讀性,而是效率:'shared_ptr'需要爲共享引用計數分配動態內存,所以'shared_ptr <...>(new ...)'涉及兩個(通常是昂貴的)內存分配。另一方面,'make_shared'同時爲對象分配足夠的內存和引用計數,因此效率更高。 – 2012-05-21 09:43:39

3
  1. 複製一個shared_ptr現在成本在堆拷貝和額外的refcount遞增/遞減32個字節。決定它是否便宜,但我看不出爲什麼不傳遞const引用,特別是你已經有了一個ptr的typedef: void f(const foo_ptr &myfoo) 尤其是假設標準的no-write-permissions參數傳入C++是const引用。

  2. 我寧願沒有接受不共享指針的函數。這與Java和C#中的參數傳遞語義相似(儘管不完全相同)。爲什麼每次都要決定如何傳遞一個對象,而不是採用一種標準的方式來實現呢?與普通指針一樣,使用if(p)。布爾轉換語義非常整潔。