5.2 =delete 显式删除函数

=delete 显式删除函数用于指示编译器禁用自动生成该成员函数,任何试图调用该函数的代码都会在编译时报错。

=delete 显式删除函数可以用于任何成员函数(包括特殊成员函数和普通成员函数)。

显式删除函数的适用场景如下:

  1. 禁止拷贝(单例模式、资源独占类)。
  2. 禁止某些隐式类型转换。
  3. 禁用不需要的特定重载版本。

示例1

禁止 Complex 类型的的对象拷贝。

// filename: delete1.cpp
class Complex {
    public:
        Complex(double r=0.0, double i=0.0): real(r), image(i){}
        Complex(const Complex & other) = delete;
        Complex& operator=(const Complex & other) = delete;
   private:
        double real;
        double image;
};

int main(int argc, char * argv[]) {
    Complex c1(1, 2);
    Complex c2(c1);  // 报错,禁止拷贝构造
    Complex c3;
    c3 = c1;  // 报错,禁止拷贝

    return 0;
}

编译时报错如下:

weimz@mzstudio:~$ gcc -o delete1 delete1.cpp
delete1.cpp: In function ‘int main(int, char**)’:
delete1.cpp:13:18: error: use of deleted function ‘Complex::Complex(const Complex&)’
   13 |     Complex c2(c1);  // 报错,禁止拷贝构造
      |                  ^
delete1.cpp:4:9: note: declared here
    4 |         Complex(const Complex & other) = delete;
      |         ^~~~~~~
delete1.cpp:13:18: note: use ‘-fdiagnostics-all-candidates’ to display considered candidates
   13 |     Complex c2(c1);  // 报错,禁止拷贝构造
      |                  ^
delete1.cpp:15:10: error: use of deleted function ‘Complex Complex::operator=(const Complex&)’
   15 |     c3 = c1;  // 报错,禁止拷贝赋值
      |          ^~
delete1.cpp:5:17: note: declared here
    5 |         Complex operator=(const Complex & other) = delete;
      |                 ^~~~~~

示例2

禁止 double 类型转为 int 类型的隐式类型转换。

// filename: delete2.cpp
class Human {
    public:
        Human(): age(0){}
        void set_age(int a) { age = a; }
        void set_age(double) = delete; // 禁止设置浮点数年龄。
   private:
        int age;
};

int main(int argc, char * argv[]) {
    Human h1;
    h1.set_age(18);  // 正确用法。
    h1.set_age(16.5);  // 错误,已经禁止 set_age(double)。

    return 0;
}

编译时报错如下:

weimz@mzstudio:~$ g++ -o default2 default2.cpp
default2.cpp: In function ‘int main(int, char**)’:
default2.cpp:14:15: error: use of deleted function ‘void Human::set_age(double)’
   14 |     h1.set_age(16.5);  // 错误,已经禁止 set_age(double)。
      |     ~~~~~~~~~~^~~~~~
default2.cpp:6:14: note: declared here
    6 |         void set_age(double) = delete; // 禁止设置浮点数年龄。
      |              ^~~~~~~
default2.cpp:14:15: note: use ‘-fdiagnostics-all-candidates’ to display considered candidates
   14 |     h1.set_age(16.5);  // 错误,已经禁止 set_age(double)。
      |     ~~~~~~~~~~^~~~~~
make: *** [Makefile:35:default1] 错误 1

示例3

禁止 Image 类型的对象只能移动构造或移动赋值,不能复制。

// filename: delete3.cpp
class Image {
    public:
        Image() = default

        // 只允许移动,不允许拷贝
        Image(Image&&) = default;
        Image& operator=(Image&&) = default;
        // 禁止复制
        Image(const Image&) = delete;
        Image& operator=(const Image&) = delete;
};