2012-08-05 134 views
14

的的std :: shared_ptr的構造並不表現爲我所料:的std :: shared_ptr的和初始化列表

#include <iostream> 
#include <vector> 

void func(std::vector<std::string> strings) 
{ 
    for (auto const& string : strings) 
    { 
     std::cout << string << '\n'; 
    } 
} 

struct Func 
{ 
    Func(std::vector<std::string> strings) 
    { 
     for (auto& string : strings) 
     { 
      std::cout << string << '\n'; 
     } 
    } 
}; 

int main(int argc, const char * argv[]) 
{ 

    func({"foo", "bar", "baz"}); 
    Func({"foo", "bar", "baz"}); 
    //auto ptr = std::make_shared<Func>({"foo", "bar", "baz"}); // won't compile. 
    //auto ptr = std::make_shared<Func>{"foo", "bar", "baz"}; // nor this. 
    return 0; 
} 

我是不是做錯了什麼或者是編譯器?編譯器是:

$鐺++ --version 蘋果鐺版本4.0(標籤/蘋果/鐺 - 421.0.57)(基於LLVM 3.1svn)

編輯:shared_ptr的,而不是make_shared。

這裏的錯誤:

make -k 
clang++ -std=c++11 -stdlib=libc++ main.cc -o main 
main.cc:28:18: error: no matching function for call to 'make_shared' 
     auto ptr = std::make_shared<Func>({"foo", "bar", "baz"}); 
       ^~~~~~~~~~~~~~~~~~~~~~ 
/usr/bin/../lib/c++/v1/memory:4621:1: note: candidate function not viable: 
    requires 0 arguments, but 1 was provided 
make_shared(_Args&& ...__args) 
^ 
1 error generated. 

回答

21

試試這個:

auto ptr = std::make_shared<Func>(std::initializer_list<std::string>{"foo", "bar", "baz"}); 

鏘不願意推斷的{"foo", "bar", "baz"}類型。我目前不確定這是否是該語言應該工作的方式,或者我們正在查看編譯器錯誤。

+5

最後我聽說,完美的轉發實際上並不完美,當初始化列表有關。 – Puppy 2012-08-06 00:10:46

+2

{「foo」,「bar」,「baz」}不是一個表達式,因此沒有類型(除了與auto一起使用)..雖然這將是很好的 – Cubbi 2012-08-06 00:22:04

3

您需要使用make_shared,如果你想創建一個新的對象,從這些參數構造,指向一個shared_ptrshared_ptr<T>就像是一個指向T的指針 - 它需要使用指針T而不是T來構建。

編輯:當涉及到初始化列表(這是糟糕的)時,完美轉發實際上並不完美。這不是編譯器中的錯誤。您將不得不手動創建類型Func的右值。

+0

對不起,問題在於make_shared。我將它改爲shared_ptr,同時開啓。 – dpj 2012-08-05 23:33:55

4

shared_ptr<T>的構造函數將一個類型爲T*的指針作爲它的參數,假定它指向一個動態分配的資源(或者至少可以被刪除器釋放的東西)。另一方面,make_shared爲您做了構建並直接使用構造函數參數。

因此,無論你說的這個:

std::shared_ptr<Foo> p(new Foo('a', true, Blue)); 

或者,更好,更有效地:

auto p = std::make_shared<Foo>('a', true, Blue); 

後一種形式負責分配和建設的你,並在這個過程中產生更有效的實施。

你當然也可以說make_shared<Foo>(Foo('a', true, Blue)),但這隻會產生一個不必要的副本(可能會被忽略),更重要的是它會產生不必要的冗餘。 [編輯]爲了初始化您的載體,這可能是最好的方法:

auto p = std::make_shared<Func>(std::vector<std::string>({"a", "b", "c"})); 

重要的一點是,雖然,make_shared進行動態分配你,而共享PTR構造確實不是,而是取得所有權

+0

對不起。你們這麼快!問題在於make_shared。 – dpj 2012-08-05 23:36:19

+0

「*但這隻會造成不必要的副本*」一個不必要的舉動。 – ildjarn 2012-08-05 23:36:52

+0

@ildjarn:那一切都依賴,不是嗎?無論如何,「移動」只是一個優化的副本:-) – 2012-08-05 23:38:54