【问题标题】:Error: Use of deleted function std::unique_ptr错误:使用已删除的函数 std::unique_ptr
【发布时间】:2022-01-07 22:58:30
【问题描述】:

我正在尝试将 unique_ptr 传递给自定义矢量类,但我收到主题标题中的错误。

我了解您无法复制 unique_ptr,因此我在传递它时尝试使用 std::move() ,但这似乎并不能解决我的问题...我哪里出错了?

提前致谢

template<typename T>
class VectorSelectable {
public:
    void Add(const T& v) { 
        m_Items.push_back(move(v)); 
    }
private:
    vector<T> m_Items;
};

class FunctionType {
    int m_Data;
};

int main()
{
    VectorSelectable<unique_ptr<FunctionType>> vec;
    vec.Add(move(make_unique<FunctionType>()));
    return 0;
}

编辑:将 'const' 添加到 'Add(const T& v)'

【问题讨论】:

  • 您知道您从std::move 获得的右值引用已经衰减回Add 方法中的左值引用,因为您编写了参数列表T&amp; v。如果你想让它占用T&amp;&amp; v,你必须写那个。
  • 移动 const 对象在大多数情况下会导致复制...

标签: c++ unique-ptr deleted-functions


【解决方案1】:

如果您想同时允许 copy-via-const-ref 和 move-via-rvalue-ref,您可以模板化您的 Add 方法并使用通用转发引用技术,或者显式编写两个重载:

    void Add(const T& v) { 
        m_Items.push_back(v); 
    }
    void Add(T&& v) { 
        m_Items.push_back(std::move(v)); 
    }

    template <typename U>
    void Add(U&& v) { 
        m_Items.push_back(std::forward<U>(v)); 
    }

【讨论】:

  • 谢谢,2 个重载是完美的解决方案 :)
  • 是的,这取决于调用者在这里选择正确的重载,并且它适用于给定的代码。我们可以使用 SFINAE 完全禁用复制重载,但对于所问的问题,它不是必需的。
【解决方案2】:

Add() 接受T 的左值引用,但move(make_unique&lt;FunctionType&gt;()) 返回右值引用,您不能将右值绑定到左值引用。

您可以将Add() 转换为模板函数,并使用转发引用来接受左值和右值并将它们移动到您的m_Items 中。

template<class U>
void Add(U&& v) { 
    m_Items.push_back(move(v)); 
}

Demo.

【讨论】:

  • 我意识到我忘记在 'Add(const T& v)' 中添加 const,这仍然适用吗?
  • 没有。你不能移动const T&amp;,因为它是const
【解决方案3】:

@Max Peglar-Willis 这里的问题是,在某个地方,您的代码正在尝试调用“复制分配”运算符。

这会导致编译器尝试生成一个复制赋值运算符,该运算符调用所有子对象的复制赋值运算符。最终,这会导致尝试复制 unique_ptr,

不可能的操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-17
    • 1970-01-01
    • 2015-02-03
    • 1970-01-01
    • 2020-09-16
    相关资源
    最近更新 更多