2012-08-05 103 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