unique_ptr-based pimpl class 中的移动构造函数是否需要完整类型?
Does the move constructor in a unique_ptr-based pimpl class require a complete type?
如果我使用 unique_ptr<T>
构建一个 pimpl class,我知道编译器生成的函数调用 T
的析构函数需要 T
是一个完整类型。但是 pimpl class 的移动构造函数呢?编译器生成的版本只调用 unique_ptr
的移动构造函数。该功能不会破坏任何东西。此外,pimpl class 生成的移动构造函数是隐式的 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
产生的内存泄漏并不重要。
这么近。
Furthermore, the pimpl class's generated move constructor is
implicitly noexcept
, so there's no possibility of its body throwing
an exception that would cause it to have to back out and destroy the
unique_ptr
subobject.
In a non-delegating constructor, the destructor for each potentially
constructed subobject of class type is potentially invoked (12.4). [
Note: This provision ensures that destructors can be called for fully-constructed sub-objects in case an exception is thrown (15.2).
—end note ]
这是一个 odr-use ([basic.def.odr]/3),因此导致 unique_ptr
的析构函数的隐式实例化,最终需要一个完整的类型。
noexcept
构造函数没有特殊情况。
如果我使用 unique_ptr<T>
构建一个 pimpl class,我知道编译器生成的函数调用 T
的析构函数需要 T
是一个完整类型。但是 pimpl class 的移动构造函数呢?编译器生成的版本只调用 unique_ptr
的移动构造函数。该功能不会破坏任何东西。此外,pimpl class 生成的移动构造函数是隐式的 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
产生的内存泄漏并不重要。
这么近。
Furthermore, the pimpl class's generated move constructor is implicitly
noexcept
, so there's no possibility of its body throwing an exception that would cause it to have to back out and destroy theunique_ptr
subobject.
In a non-delegating constructor, the destructor for each potentially constructed subobject of class type is potentially invoked (12.4). [ Note: This provision ensures that destructors can be called for fully-constructed sub-objects in case an exception is thrown (15.2). —end note ]
这是一个 odr-use ([basic.def.odr]/3),因此导致 unique_ptr
的析构函数的隐式实例化,最终需要一个完整的类型。
noexcept
构造函数没有特殊情况。