2012-08-17 231 views
5

下面是關於創建Stuff並賦予Foo所有權的合理且有效的方法嗎?將std :: shared_ptr傳遞給構造函數

class Foo 
{ 
    explicit Foo(const std::shared_ptr<Stuff>& myStuff) 
     : m_myStuff(myStuff) 
    { 
    } 

    ... 

private: 
    const std::shared_ptr<Stuff> m_myStuff; 
} 

std::shared_ptr<Stuff> foosStuff(new Stuff()); 
Foo f(foosStuff); 
+0

@sellibitze typo – Baz 2012-08-17 08:41:49

+6

不是真的,'Foo'不*取*擁有權。 'shared_ptr'的要點是*共享*所有權。 – juanchopanza 2012-08-17 08:43:44

+0

或者更喜歡'std :: shared_ptr foosStuff(new Stuff());' – stefaanv 2012-08-17 08:47:37

回答

16

既然你有興趣的效率,我想強調兩點:

shared_ptr的<>是許多標準庫類型,其中一招構造比一個拷貝構造更便宜的一個。複製構造shared_ptr的速度較慢,因爲複製要求引用計數器以原子方式遞增,而移動shared_ptr則根本不需要接觸引用的數據或計數器。從Dave Abrahams的文章「Want Speed? Pass by value!」中可以瞭解到,在某些情況下,按價值獲取函數參數實際上是有益的。這是其中一個案件:

class Foo 
{ 
    explicit Foo(std::shared_ptr<Stuff> myStuff) 
    : m_myStuff(move(myStuff)) 
    {} 

    ... 

private: 
    std::shared_ptr<Stuff> m_myStuff; 
}; 

現在你可以寫

Foo f (std::make_shared<Stuff>()); 

,其中參數是一個臨時的,沒有的shared_ptr被抄過(剛搬到一次或兩次)。

這裏使用std :: make_shared具有隻有一個分配完成的優點。在你的情況下,你自己分配了Stuff對象,並且shared_ptr構造函數也必須動態地分配引用計數器和刪除器。 make_shared只用一個分配就可以完成所有的工作。

+1

我喜歡這個make_shared函數 – Baz 2012-08-17 08:54:04

+1

btw:如果你改變爲std :: unique_ptr你實際上_HAVE_傳遞它的價值;) – sellibitze 2012-08-17 08:56:25

+0

@sellibitze將類shared_ptr傳遞給它的構造函數有什麼好處如果你不打算保留它。當然在這種情況下,最好傳入一個unique_ptr並讓該類從其構造shared_ptr? – jleahy 2012-08-17 09:32:03

4

是的,這是完全合理的。這樣,管理共享指針所涉及的工作只需要進行一次,而不是按值傳遞兩次。你也可以考慮使用make_shared來避免複製構造。

std::shared_ptr<Stuff> foosStuff(std::make_shared<Stuff>()); 

你可以做的唯一的改進是,如果美孚是成爲唯一擁有者(即你不打算繼續foosStuff創建美孚之後各地),那麼你可以切換到使用一個std ::的unique_ptr或boost :: scoped_ptr(這是pre-C++ 11的等價物),這將有較少的開銷。

+0

好吧,我應該研究更多關於其他智能指針的知識,因爲我只是非常熟悉shared_ptr。 – Baz 2012-08-17 08:43:15

+0

什麼是'scoped_ptr',它不是C++的一部分?也許你的意思是'std :: unique_ptr'?爲什麼自定義刪除? – 2012-08-17 08:54:20

+0

@ChristianRau:我想這意味着'boost :: scope_ptr'。 deleter位可能是對較早(隱形)編輯的過時引用? – 2012-08-17 09:00:45

3

這可能是更有效的有make_foo幫手:

Foo make_foo() { return Foo(std::make_shared<Stuff>()); } 

現在你可以說auto f = make_foo();。或者至少自己使用make_shared調用,因爲生成的shared_ptr可能比由new表達式構造的效率更高。

auto f = Foo::make(true, 'x', Blue); 

這就是說,除非你:如果Stuff其實需要構造函數參數,私人輔助構造可能是合適的:

struct Foo 
{ 
    template <typename ...Args> 
    static Foo make(Args &&... args) 
    { 
     return Foo(direct_construct(), std::forward<Args>(args)...); 
    }; 

private: 

    struct direct_construct{}; 

    template <typeaname ...Args> 
    Foo(direct_construct, Args &&... args) 
    : m_myStuff(std::make_shared<Stuff>(std::forward<Args>(args)...)) // #1 
    { } 
}; 

您可以包裹Foo::make到上述make_foo,或直接使用它真的是分享所有權,std::unique_ptr<Stuff>聽起來像更可取的方法:它在概念上更簡單,也更有效。在這種情況下,您會在標記爲#1的行中說m_myStuff(new Stuff(std::forward<Args>(args)...))

+0

+1爲提及unique_ptr :) – sellibitze 2012-08-17 08:51:10

相關問題