为什么我必须在声明析构函数时声明复制和移动构造函数?

MiP*_*MiP 7 c++ resharper c++11

我有一个NonCopyable类和一个Application类派生自NonCopyable:

class NonCopyable
{
public:
    NonCopyable() = default;
    virtual ~NonCopyable() = default;
    NonCopyable(NonCopyable const&) = delete;
    NonCopyable& operator =(NonCopyable const&) = delete;
    NonCopyable(NonCopyable&&) = delete;
    NonCopyable& operator=(NonCopyable&&) = delete;
};

class Application : public NonCopyable
{
public:
    ~Application() { /* ...delete stuff... */ }
};
Run Code Online (Sandbox Code Playgroud)

如您所见,我不需要重新声明已删除的移动构造函数或赋值运算符,因为我已在基类中声明它们.但为什么Resharper建议我宣布其他特殊成员职能呢?它说:

Application定义了非默认的析构函数,但没有定义复制构造函数,复制赋值运算符,移动构造函数或移动赋值运算符[hicpp-special-member-functions].

还有[cppcoreguidelines-special-member-functions]提醒具有相同的消息.

目前的解决方法是明确地写下所有这些以使警告消失:

class Application : public NonCopyable
{
public:
    ~Application() { /* ...delete stuff... */ }
    Application(Application const&) = delete;
    Application& operator =(Application const&) = delete;
    Application(Application&&) = delete;
    Application& operator=(Application&&) = delete;
};
Run Code Online (Sandbox Code Playgroud)

Pet*_*ter 6

通常,如果类定义的析构函数与编译器自动生成的析构函数不同,则其目的是释放该类管理的某些资源。

如果析构函数必须释放某些资源,那么通常还需要用户定义的构造函数来初始化该资源,用户定义的复制构造函数来创建相同类型的现有对象所拥有的资源的副本,以及一个用户定义的移动构造函数,用于从不再存在的临时对象中获取资源的所有权。

类似地,还需要复制赋值运算符和移动赋值运算符,以便类似的表达式a = b可以将资源复制或移动到现有对象。

如果类没有一个或多个这些构造函数或赋值运算符,那么实际上,使用多个对象的代码通常不会表现一致(例如,析构函数释放一个资源两次,因为它被两个对象共享,从而导致未定义的行为, ETC)。

当然,在某些情况下,类不需要完整的构造函数、赋值运算符和析构函数。然而,忽略其中一个通常是程序员的错误(与预期效果不同),因此代码分析工具经常会抱怨这种情况。


Ap3*_*p31 1

据 ReSharper 所知,您定义了一个不平凡的析构函数,并且没有遵循 3/5 规则的其余部分。是的,默认情况下会删除复制/移动构造函数,因为它们是在基类中删除的,但是 ReSharper 如何知道这是理想的行为?因此,除非您明确将它们标记为 ,否则它警告您是有意义的delete

delete您可以按照您的建议,使用编译指示或显式构造函数/赋值 在本地禁用警告。

作为解决方法,您可以引入虚拟cleanup()方法,从析构函数调用它NonCopyable,并在派生类中重写它(而不是析构函数)。