使用GCC 4.7初始化初始化程序列表中的unique_ptrs容器失败
我试图以等同于Bjarne Stroustrup的C ++ 11 FAQ的例子初始化一个std::vector<std::unique_ptr<std::string>>
:
using namespace std; vector<unique_ptr<string>> vs { new string{"Doug"}, new string{"Adams"} }; // fails unique_ptr<string> ps { new string{"42"} }; // OK
我看不出为什么这个语法会失败。 这种初始化容器有什么问题吗?
编译器的错误信息是巨大的; 我find的相关细分如下:
/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>&)'
有什么办法来解决这个错误?
unique_ptr
的构造函数是explicit
。 所以你不能用new string{"foo"}
隐式地创build一个。 它需要像unique_ptr<string>{ new string{"foo"} }
。
这导致我们这个
vector<unique_ptr<string>> vs { unique_ptr<string>{ new string{"Doug"} }, unique_ptr<string>{ new string{"Adams"} } };
但是,如果其中一个构造函数失败,可能会泄漏。 使用make_unique
更安全:
vector<unique_ptr<string>> vs { make_unique<string>("Doug"), make_unique<string>("Adams") };
但是… initializer_list
总是执行副本,而unique_ptr
不可复制。 这是真正讨厌初始化列表的东西。 你可以绕过它 ,或者emplace_back
到emplace_back
初始化。
如果你实际上用智能指针来pipe理string
,而不仅仅是这个例子,那么你可以做得更好:只要创build一个vector<string>
。 std::string
已经处理了它使用的资源。
在“修复”你的例子之后:
#include <vector> #include <memory> #include <string> int main() { std::vector<std::unique_ptr<std::string>> vs = { { new std::string{"Doug"} }, { new std::string{"Adams"} } }; // fails std::unique_ptr<std::string> ps { new std::string{"42"} }; // OK }
我得到了非常明确的错误信息:
error: converting to 'std::unique_ptr<std::basic_string<char> >' from initializer list would use explicit constructor 'std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer) [with _Tp = std::basic_string<char>, _Dp = std::default_delete<std::basic_string<char> >, std::unique_ptr<_Tp, _Dp>::pointer = std::basic_string<char>*]'
这个错误告诉我们不可能使用unique_ptr
的显式构造器。