10

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

编译器-资源管理器中的代码

我的理解是,该=符号导致复制初始化,但是,由于复制省略,我希望m_ptr2仍然可以初始化而不会失败。

为什么m_ptr2需要 ForwardDeclared 的析构函数并且 Clang/GCC 对此是否正确?(奖励:得出 m_ptr1 被 MSVC 错误接受的结论是否正确?)

4

1 回答 1

1

我的理解是 = 符号会导致复制初始化,但是,由于复制省略,我希望 m_ptr2 仍然会被初始化而不会失败。

复制省略要求该类型的析构函数可访问且不可删除,即使没有对象被销毁,请参阅https://en.cppreference.com/w/cpp/language/copy_elision

所以 GCC 和 Clang 正确地检查了析构函数,这对于不完整的类型是无效的ForwardDeclared

奖励:得出 m_ptr1 被 MSVC 错误接受的结论是否正确?

是的,MSVC 在这里不正确。

请参阅为什么 C++ 中强制 RVO 需要公共析构函数?解释为什么强制复制省略不适用。

为什么 m_ptr2 需要 ForwardDeclared 的析构函数并且 Clang/GCC 对此是否正确?

同样的推理也适用于复制省略的有效析构函数的必要性。

于 2021-08-06T06:29:49.843 回答