以下代码使用 MSVC (/permissive-) 编译,但无法使用 GCC/Clang 编译 m_ptr1 和 m_ptr2。
#include <memory>
struct ForwardDeclared;
class A {
public:
explicit A();
~A();
private:
std::unique_ptr<ForwardDeclared> m_ptr1 = nullptr; // not ok
std::unique_ptr<ForwardDeclared> m_ptr2 {std::unique_ptr<ForwardDeclared>{}}; // not ok
std::unique_ptr<ForwardDeclared> m_ptr3 {nullptr}; // ok
std::unique_ptr<ForwardDeclared> m_ptr4; // ok
};
int main() {
A a;
return 0;
}
Code at compiler-explorer我的理解是
=
签名结果 copy initialization但是,感谢 copy elision我希望 m_ptr2
仍然会被初始化而不会失败。为什么
m_ptr2
需要 ForwardDeclared 的析构函数,Clang/GCC 是否正确? (奖励:得出 m_ptr1 被 MSVC 错误接受的结论是否正确?)
最佳答案
My understanding is that the = sign results in copy initialization, however, thanks to copy elision I would expect m_ptr2 would still be initialized without failure.
复制省略要求该类型的析构函数可访问且不可删除,即使没有对象被销毁,请参阅 https://en.cppreference.com/w/cpp/language/copy_elision
所以GCC和Clang正确检查析构函数,对不完整类型
ForwardDeclared
无效.Bonus: Is it correct to conclude that m_ptr1 is incorrectly accepted by MSVC?
是的,MSVC 在这里不正确。
见 Why is public destructor necessary for mandatory RVO in C++?解释为什么强制复制省略不适用。
Why does m_ptr2 require a destructor of ForwardDeclared and are Clang/GCC correct for this?
关于复制省略的有效析构函数的必要性,同样的推理适用于此。
关于c++ - 为什么在 C++17 中复制初始化需要析构函数并保证移动/复制省略?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65286451/