> 文章列表 > C++11 关键字 =default 和 =delete

C++11 关键字 =default 和 =delete

C++11 关键字 =default 和 =delete

1. = default

1.1 引入背景

C++ 的类有几个特殊的成员函数,分别为:默认构造函数,析构函数,拷贝函数、拷贝赋值函数、移动构造函数、移动赋值函数。

如果程序没有显式地为一个类定义某个特殊成员函数,而又需要用到该特殊成员函数时,编译器会隐式地为这个类生成一个默认的特殊成员函数。

class X {
private:int a;
};
X x;   //可以编译通过,编译器隐式生成默认构造函数

但是如果X 显式的自定义了非默认构造函数,却没有定义默认构造函数,下面的代码会出现编译错误。

class X{
public:X(int i){a = i;}
private:int a;
};X x; // 错误,默认构造函数 X::X()不存在

为了解决上面的问题,我们需要自定义默认构造函数,如下:

class X{
public:X(){};  // 手动定义默认构造函数X(int i){a = i;}
private:int a;
};X x; //正确,默认构造函数 X::X()不存在

但是手动编写存在两个问题:

  • 程序员工作量变大
  • 没有编译器自动生成的默认特殊构造函数效率高

不能看到上面的例子中,工作量不大,就认为上面的第一个问题不存在。请看下面的例子:

class A
{
public:A(int ii, char cc):i(ii),c(cc){}A(const A& a);
private:int i;char c;
};

上述代码如果要手动写出拷贝构造函数,如下:

A(const A& a):i(a.i),c(a.c){}

为了解决上述的两个问题,C++ 11标准引入了一个新特性:default 函数

1.2 使用

class X {
public:int f() = default: //错误, f()非特殊成员函数X(int) = default; //错误, 非特殊成员函数X(int i = 1) = default; // 错误, 含有默认参数
}

=default; 只针对特殊的成员函数,用以告知编译器,由编译器实现。

例如,

class X{
public:X(int i){a = i;}
private:int a;
};
X x; // 错误,默认构造函数 X::X()不存在

类X已经声明了构造函数,编译器不会在生成一个没有参数的默认构造函数。

但是,如果想要使用默认构造函数,在C98时需要在类中声明并实现。C++11 引入=default 就是为了避免实现这一步,而改为由编译器实现。

2. =delete

2.1 引入背景

为了显式的禁用某个函数,C++11 标准引入了一个新特性:delete 函数。

2.2 使用

class X{            
public: X(); X(const X&) = delete;  // 声明拷贝构造函数为 deleted 函数X& operator = (const X &) = delete; // 声明拷贝赋值操作符为 deleted 函数
}; class Y{ 
public: // 禁止使用者在堆上申请对象void *operator new(size_t) = delete; void *operator new[](size_t) = delete; 
}; 
  • 必须在函数第一次声明的时候将其声明为 deleted 函数
  • 不同于default,delete没有限制为特殊成员函数才能使用delete
bool IsLucky(int number);        // original function
bool IsLucky(char) = delete;     // reject chars
bool IsLucky(bool) = delete;     // reject bools
bool IsLucky(double) = delete;   // reject doubles and floats

在调用时:

if (IsLucky('a')) …     // error !    call to deleted function
if (IsLucky(true)) …    // error !
if (IsLucky(3.5)) …     // error !