【问题标题】:What is the correct usage of std::unique_ptr while pushing into std::vector [duplicate]推入 std::vector 时 std::unique_ptr 的正确用法是什么 [重复]
【发布时间】:2013-01-07 04:42:21
【问题描述】:

我想在我的类中有一个指向对象的指针向量。为了避免为它创建析构函数,我想使用std::unique_ptr,因为对象是在我的类中创建/拥有/销毁的,但是我有一个我无法理解的编译器错误。下一个代码将作为我的问题的简短示例:

std::unique_ptr<int> createPtr(int value)
{
    std::unique_ptr<int> ptr(new int(value));
    return ptr;
};

int main()
{
    std::vector<std::unique_ptr<int>> vec;
    vec.push_back(createPtr(1));

    std::unique_ptr<int> ptr = createPtr(2);
    vec.push_back(ptr);//error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
}

您能否解释一下为什么会出现此错误以及std::unique_ptr 的正确用法是什么?

【问题讨论】:

  • 存储指向int 的指针而不是向量中的值有什么意义?
  • 如果您正在考虑使用std::unique_ptr&lt;&gt;,那么您可能没有有一个“对象向量”,而是一个“指向对象的指针向量”。如果你有一个“对象向量”,那么销毁会自动正确发生。
  • @TadeuszKopec 请阅读问题
  • @Robᵩ 我会编辑问题,我想说的是指向对象的指针

标签: c++ c++11 vector unique-ptr


【解决方案1】:

要么:

vec.push_back(std::move(ptr));

或者:

vec.emplace_back(createPtr(2));

【讨论】:

  • 它解决了问题,但你能解释一下问题吗?
  • @Felics 问题是unique_ptr 不允许复制构造,因此尝试push_back ptr 失败,因为它试图调用复制构造函数。然而,移动构造函数是可访问的,并且 Kerrek 的两个解决方案都调用它而不是复制构造函数。
  • @Praetorian emplace_back 怎么样?
  • @David 同样处理,createPtr 按值返回 unique_ptremplace_back 将尝试使用此参数调用 unique_ptr 构造函数。匹配的构造函数是移动构造函数。
  • @David emplace_back 表示,就地创建。以下内容不进行复制或移动。 vec.emplace_back(new int(34))该值在向量中就地构造
【解决方案2】:

考虑vec.push_back()。它有两个重载,采用const std::unique_ptr&lt;int&gt;&amp;std::unique_ptr&lt;int&gt;&amp;&amp;。第一个重载永远不能使用。这是因为vector&lt;&gt; 要求类型是可分配的或可移动的(C++11 添加)。 “可分配性”意味着复制。 push_back(const T&amp;) 将尝试将传入的值复制(分配)到容器末尾的新空间。 std::unique_ptr&lt;&gt; 表示由单个所有者拥有的资源。通过复制它(指针)将出现多个所有者。因为 unique_ptr 不可复制

说了这么多,你只能使用T&amp;&amp;重载。

createPtr() 返回std::unique_ptr&lt;int&gt;,但由于这是一个临时结果(函数返回值),它被认为是一个右值引用(隐式)。这就是为什么可以使用它的原因。

ptr 只是一个std::unique_ptr&lt;int&gt;,它是一个左值引用(无论你是否将 && 放在它旁边,因为 named 右值仍然被视为左值)。左值永远不会隐式转换为右值(完全不安全)。但是你基本上可以通过使用std::move() 告诉编译器“好的,你可以接受我传递给你的对象,我保证我不会期望参数保持不变”。

【讨论】:

    【解决方案3】:

    你有一个unique_ptr:

    std::unique_ptr<int> ptr = createPtr(2);
    

    现在你把它的副本放在向量中:

    vec.push_back(ptr);
    

    现在您有两个具有相同值的unique_ptrs。如果允许,它将不是唯一的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-18
      • 1970-01-01
      • 2019-11-07
      • 1970-01-01
      • 2013-03-06
      • 2018-02-02
      • 2015-10-11
      相关资源
      最近更新 更多