std :: shared_ptr和初始化列表

时间:2012-08-05 23:27:46

标签: c++ c++11 clang shared-ptr initializer-list

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;
}

我做错了什么还是编译器?编译器是:

$ clang ++ --version Apple clang 4.0版(标签/ Apple / clang-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.

3 个答案:

答案 0 :(得分:23)

试试这个:

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

Clang不愿意推断出{"foo", "bar", "baz"}的类型。我目前还不确定这是该语言的工作方式,还是我们正在查看编译器错误。

答案 1 :(得分:5)

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 为您执行动态分配,而shared-ptr构造函数,而不是取得所有权

答案 2 :(得分:3)

如果要创建一个由make_shared指向的参数构造的新对象,则需要使用shared_ptrshared_ptr<T>就像指向T的指针 - 它需要使用指针构建到T,而不是T

编辑:当涉及初始化列表时,完美转发实际上并不完美(这很糟糕)。这不是编译器中的错误。您必须手动创建Func类型的右值。