【问题标题】:Referencing deleted function when using unique_ptr使用 unique_ptr 时引用已删除的函数
【发布时间】:2017-02-16 23:20:44
【问题描述】:

我有以下类定义:

class InterpolatedSpreadConnector
{
public:
    ~InterpolatedSpreadConnector() = default;
    GPUImage* operator()() override;

    GPUImage* AncestorReducedConnectivity = nullptr;
    GPUImage* OffspringReducedConnectivity = nullptr;
};

,当在声明 auto connector = InterpolatedSpreadConnector(); 中使用时,它工作得很好。但是,我想将这些原始指针更改为 unique_ptrs。

在定义中包含memory 并用std::unique_ptr<GPUImage> 成员替换原始指针会给我InterpolatedSpreadConnector 复制构造函数上的attempting to reference deleted function 错误。奇怪的是,如果我将 unique_ptr 替换为 shared_ptr,错误就会消失。

谁能解释为什么会这样?

【问题讨论】:

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


【解决方案1】:

要使此代码正常工作,在 C++17 之前,您需要为您的类定义一个移动构造函数。这可能很简单:

 InterpolatedSpreadConnector(InterpolatedSpreadConnector &&) = default;

您的用户定义的析构函数意味着移动构造函数的隐式生成被抑制。

如果没有移动构造函数,复制/移动操作会退回到复制构造函数,这会导致编译错误,因为隐式生成的复制构造函数被删除,因为unique_ptr 有一个已删除的复制构造函数。


在 C++14 及更早版本中,auto x = X(); 在概念上意味着我们创建一个临时的X,然后从临时复制/移动构造x 并销毁该临时。允许编译器 elide 临时,但该过程的正确构造函数必须仍然存在。

但是在 C++17 中,auto x = X(); 将被定义为与 X x{}; 相同的含义。

所以你的代码可以在 C++17 中运行,尽管定义移动构造函数是个好主意;或者最好删除析构函数定义(参见Rule of zero)。

【讨论】:

  • 我明白了。我认为复制省略会自动跳过复制构造并在此类情况下假定正常构造。
  • @KristianD'Amato 确实如此,但是如果没有发生复制省略,将使用的构造函数必须存在并且可以访问。基本原理是,如果编译器决定执行或不执行复制省略,则程序不应根据该选择突然编译失败。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-02
  • 2022-01-07
  • 2020-08-17
  • 2015-07-23
  • 1970-01-01
  • 2016-08-17
相关资源
最近更新 更多