基于unique_ptr的pimpl类中的move构造函数是否需要一个完整的类型
Does the move constructor in a unique_ptr-based pimpl class require a complete type?
如果我使用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
构造函数没有特殊情况。
相关文章:
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 检查一个类型是否直接派生自"enable if"上下文中的另一个类型(是其子类型)
- 给定一个类型,如何派生一个泛型更广泛的类型(例如,用于溢出安全求和)?
- 更改可变参数模板中的最后一个类型
- 如何构造一个类型特征,可以判断一个类型的私有方法是否可以在另一个类型的构造函数中调用?
- 有没有办法同时将一个类型分配给C++中的多个模板?
- C++:可以模板化一个类型名称吗
- 有没有一种方法可以使用SFINAE来检测一个类型是否实现了给定的抽象基类
- 给定一个类型为 Container:<T>:Iterator 的函数参数,如何为某些类型的 T 实现特定的重载?
- 期望一个类型,得到一个模板
- 初始化一个类型向量的巨大向量<int>
- 我可以使用预处理器将一个类型声明替换为另一个类型声明吗?
- 具有多种类型的类数组?如何访问数组中的一个类型
- Opencv C++ 声明一个类型为 uint8 的矩阵
- 模板参数列表中只有一个类型名称是什么意思?
- C++模板部分特化:为什么我无法匹配可变参数模板中的最后一个类型
- 为什么我们有一个类型不匹配
- 在函数模板中将一个类型名映射到另一个类型名
- 创建一个类型bool的向量,其中所有值均可初始化为true
- 在C API中定义了一个类型,如何将其与命名空间中的C++类相关联