10 November 2022

C++ 核心指南目录

C.81: Use =delete when you want to disable default behaviour (without wanting an alternative)

理由

某些情况,不需要默认操作。

class Immortal {
public:
    ~Immortal() = delete;   // do not allow destruction
    // ...
};

void use()
{
    Immortal ugh;   // error: ugh cannot be destroyed
    Immortal* p = new Immortal{};
    delete p;       // error: cannot destroy *p
}
int main()
{
    use();
}
C-src-xCgZfR.cpp: In function 'void use()':
C-src-xCgZfR.cpp:18:14: error: use of deleted function 'Immortal::~Immortal()'
   18 |     Immortal ugh;   // error: ugh cannot be destroyed
      |              ^~~
C-src-xCgZfR.cpp:12:5: note: declared here
   12 |     ~Immortal() = delete;   // do not allow destruction
      |     ^
C-src-xCgZfR.cpp:20:12: error: use of deleted function 'Immortal::~Immortal()'
   20 |     delete p;       // error: cannot destroy *p
      |            ^
C-src-xCgZfR.cpp:12:5: note: declared here
   12 |     ~Immortal() = delete;   // do not allow destruction
      |     ^

例子

你可以移动unique_ptr但不能拷贝它。要实现这种要求,可以将左值拷贝函数删掉。

template<class T, class D = default_delete<T>> class unique_ptr {
public:
    // ...
    constexpr unique_ptr() noexcept;
    explicit unique_ptr(pointer p) noexcept;
    // ...
    unique_ptr(unique_ptr&& u) noexcept;   // move constructor
    // ...
    unique_ptr(const unique_ptr&) = delete; // disable copy from lvalue
    // ...
};

unique_ptr<int> make();   // make "something" and return it by moving

void f()
{
    unique_ptr<int> pi {};
    auto pi2 {pi};      // error: no move constructor from lvalue
    auto pi3 {make()};  // OK, move: the result of make() is an rvalue
}

注意:删除的函数须是 public 的。

强化

删除/禁用某些默认操作必须是基于某个明确的目的。我们可以假设删除了默认操作的类是有问题,只有当程序员明确指出是有意为之,我们才允许。