C++ 使用 GCC 4.7 从初始化列表初始化 unique_ptrs 的容器失败

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9618268/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:04:45  来源:igfitidea点击:

Initializing container of unique_ptrs from initializer list fails with GCC 4.7

c++compiler-errorsinitializationc++11

提问by juanchopanza

I am trying to initialise an std::vector<std::unique_ptr<std::string>>in a way that is equivalent to an example from Bjarne Stroustrup's C++11 FAQ:

我正在尝试以std::vector<std::unique_ptr<std::string>>Bjarne Stroustrup 的 C++11 FAQ 中的示例等效的方式初始化 an :

using namespace std;
vector<unique_ptr<string>> vs { new string{"Doug"}, new string{"Adams"} }; // fails
unique_ptr<string> ps { new string{"42"} }; // OK

I can see no reason why this syntax should fail. Is there something wrong with this way of initializing the container?
The compiler error message is huge; the relevant segment I find is below:

我看不出为什么这种语法会失败。这种初始化容器的方式有什么问题吗?
编译器错误信息很大;我找到的相关部分如下:

/usr/lib/gcc-snapshot/lib/gcc/i686-linux-gnu/4.7.0/../../../../include/c++/4.7.0 /bits/stl_construct.h:77:7: error: no matching function for call to 'std::unique_ptr<std::basic_string<char> >::unique_ptr(std::basic_string<char>&)'

/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>&)'

What is the way to fix this error ?

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

回答by R. Martinho Fernandes

unique_ptr's constructor is explicit. So you can't create one implicitly with from new string{"foo"}. It needs to be something like unique_ptr<string>{ new string{"foo"} }.

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

Which leads us to this

这导致我们这样做

// not good
vector<unique_ptr<string>> vs {
    unique_ptr<string>{ new string{"Doug"} },
    unique_ptr<string>{ new string{"Adams"} }
};

However it may leak if one of the constructors fails. It's safer to use make_unique:

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

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

But... initializer_lists always perform copies, and unique_ptrs are not copyable. This is something really annoying about initializer lists. You can hack around it, or fallback to initialization with calls to emplace_back.

但是... initializer_lists 总是执行复制,而unique_ptrs 是不可复制的。这对于初始化列表来说真的很烦人。您可以绕过它,或者通过调用emplace_back.

If you're actually managing strings with smart pointers and it's not just for the example, then you can do even better: just make a vector<string>. The std::stringalready handles the resources it uses.

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

回答by B?ови?

After "fixing" your example:

在“修复”您的示例之后:

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

I got very a clear error message:

我收到了非常明确的错误消息:

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>*]'

This error tells us that it is not possible to use the unique_ptr's explicit contructor!

这个错误告诉我们不可能使用unique_ptr的显式构造函数!