基于unique_ptr的pimpl类中的move构造函数是否需要一个完整的类型

Does the move constructor in a unique_ptr-based pimpl class require a complete type?

本文关键字:一个 类型 是否 ptr unique pimpl 构造函数 move 基于      更新时间:2023-10-16

如果我使用unique_ptr<T>来构建一个pimpl类,我理解编译器生成的调用T的析构函数要求T是一个完整的类型。但是皮条类的move构造函数呢?编译器生成的版本只调用unique_ptr的move构造函数。这个函数不会破坏任何东西。此外,pimpl类生成的move构造函数是隐式noexcept,因此它的主体不可能抛出异常,从而导致它不得不退出并销毁unique_ptr子对象。

似乎应该编译以下代码:

#include <memory>
class Widget {                      // has implicit move ctor
  struct Impl;
  std::unique_ptr<Impl> pImpl;
};
int main()
{
  Widget *pw1 = nullptr;
  new Widget(std::move(*pw1));      // call move ctor. Rejected by
}                                   // gcc, clang, and MSVC

正如评论所说,这个代码被所有的gcc、clang和MSVC拒绝。每个都抱怨对不完整类型的无效操作。这是标准要求的吗?如果是,是哪一部分?

请注意,这里的问题是编译,因此上面代码由于取消引用空pw1指针而导致的未定义的运行时行为是不相关的。出于同样的原因,上一条语句中对new的调用所引起的内存泄漏并不重要。

如此接近。

此外,皮条类生成的move构造函数是隐含的noexcept,所以它不可能抛出身体一个异常,该异常将导致它不得不退出并销毁unique_ptr子对象。

[class.base.init]/12:

在非委托构造函数中类类型的构造子对象可能被调用(12.4)[注意:此条款确保在抛出异常的情况下,可以为完全构造的子对象调用析构函数(15.2)。--尾注]

这是一个odr使用([basic.def.odr]/3),因此导致unique_ptr的析构函数的隐式实例化,而这反过来最终需要一个完整的类型。

noexcept构造函数没有特殊情况。

相关文章: