首页 文章

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

提问于
浏览
45

我试图以与Bjarne Stroustrup's C++11 FAQ中的示例等效的方式初始化_1166208:

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

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

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

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

2 回答

  • 3

    unique_ptr 的构造函数是 explicit . 因此,您无法使用 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"} }
    };
    

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

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

    但是...... initializer_list 总是执行副本, unique_ptr s不可复制 . 这对初始化列表非常烦人 . 您可以hack around it,或通过调用 emplace_back 回退到初始化 .

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

  • 55

    在“修复”你的例子之后:

    #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 的显式构造函数 .

相关问题