c++ - 为什么在 C++17 中复制初始化需要析构函数并保证移动/复制省略?

标签 c++ c++17 language-lawyer copy-elision copy-initialization

以下代码使用 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/

相关文章:

c++ - Gcc 检查给定的类是否有operator+

c++ - 增加 SIFT 中检测到的特征数量会提高精度吗?

c++ - 如何找到 vector 中的最大元素 (C++)?

c++ - 我可以用花括号构造一个链表吗?

c++ - [basic.def.odr]/3 中的短语 `if x is an object` 的用途是什么?

c++ - GCC 编译器是否应该对这个涉及 [[fallthrough]] 属性的格式错误的 C++ 代码进行诊断?

c++ - 推导函数参数包的模板参数是否有缺陷

c - strncpy(d, s, 0) 带过去指针

c++ - 为什么从 char 转换为 std::byte 可能是未定义的行为?

c++ - std::unordered_map::insert 什么时候会失败?