初始化初始化列表中unique_ptrs的容器因GCC 4.7而失败

jua*_*nza 51 c++ compiler-errors initialization c++11

我试图以一种std::vector<std::unique_ptr<std::string>>Bjarne Stroustrup的C++ 11 FAQ相同的方式初始化一个:

using namespace std;
vector<unique_ptr<string>> vs { new string{"Doug"}, new string{"Adams"} }; // fails
unique_ptr<string> ps { new string{"42"} }; // OK
Run Code Online (Sandbox Code Playgroud)

我看不出这个语法失败的原因.这种初始化容器的方式有问题吗?
编译器错误消息很大; 我找到的相关部分如下:

/usr/lib/gcc-snapshot/lib/gcc/i686-linux-gnu/4.7.0/../../../../include/c++/4.7.0 /bits/stl_construct.h:77 :7:错误:没有匹配的调用函数 'std::unique_ptr<std::basic_string<char> >::unique_ptr(std::basic_string<char>&)'

修复此错误的方法是什么?

R. *_*des 61

unique_ptr的构造函数是explicit.所以你不能用from隐式地创建一个new string{"foo"}.它需要是类似的东西unique_ptr<string>{ new string{"foo"} }.

这导致我们这样做

// not good
vector<unique_ptr<string>> vs {
    unique_ptr<string>{ new string{"Doug"} },
    unique_ptr<string>{ new string{"Adams"} }
};
Run Code Online (Sandbox Code Playgroud)

但是,如果其中一个构造函数失败,它可能会泄漏.使用起来更安全make_unique:

// does not work
vector<unique_ptr<string>> vs {
     make_unique<string>("Doug"),
     make_unique<string>("Adams")
};
Run Code Online (Sandbox Code Playgroud)

但是...... initializer_list总是执行复制,而且unique_ptr不能复制.这对初始化列表非常烦人.您可以通过调用来解决它,或者回退到初始化emplace_back.

如果你实际上string是用智能指针来管理s并且它不仅仅是用于示例,那么你可以做得更好:只需要做一个vector<string>.在std::string已经处理了它使用的资源.

  • 是否有任何理由为什么`std :: initializer_list`不能像任何其他对象一样移动语义? (8认同)
  • 第一个例子不会泄露.初始化列表中的`,`是一个序列点(在新的,稍微麻烦的术语中,在`{a,b}`中,`a`在`b`之前排序).见C++11§8.5.4/ 4.但是,使用`make_unique`仍然是一个好主意. (5认同)

归档时间:

查看次数:

19259 次

最近记录:

8 年 前