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()不存在 

但是手动编写存在两个问题:1. 程序员工作量变大 2. 没有编译器自动生成的默认特殊构造函数效率高。

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

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标准引入了一个新特性:defaulted 函数。

1.2 使用

1.2.1 使用规则

​ (1) defaulted 函数特性仅用于类的特殊成员函数,且该特殊成员函数没有默认参数。例如:

class X {
public:
    int f() = default: //错误, f()非特殊成员函数
    X(int) = default; //错误, 非特殊成员函数
    X(int i = 1) = default; // 错误, 含有默认参数
}
//能够支持default的,都是编译器能够在该情形下明确要做什么(构造函数一般是逐bit拷贝)

(2) 既可以在类体里定义(inline),也可以在类体外(out-of-line)定义。例如

class X {
public:
    X() = default; // inline
    X(const X&); // 
    X& operator = (const X&);
    ~X() = default; // inline
}

X::X(const X&) = default; // out of line
X& X::operator = (const X&) = default; // out of line
1.2.2 析构函数中的使用

​ 先看一个例子:

class X { 
private: 
 int x; 
}; 
 
class Y: public X { 
private: 
 int y; 
}; 
 
int main(){ 
 X* x = new Y; 
 delete x; 
}

上面的程序有内存泄漏的问题,因为这种情况下,会调用基类X的析构函数,并非Y的析构函数。而且此时X 的析构函数是编译器隐式自动生成的。

为了解决上面的问题,我们可以手动将X 的析构函数定义为虚函数,如下:

class X { 
public: 
 virtual ~X(){};     // 手动定义虚析构函数
private: 
 int x; 
}; 
 
class Y: public X { 
private: 
 int y; 
}; 
 
int main(){ 
 X* x = new Y; 
 delete x; 
 }

同样,为了 1. 减轻程序员的编程工作量 2.函数执行效率,我们使用default特性,如下:

class X { 
public: 
 virtual ~X()= defaulted; // 编译器自动生成 defaulted 函数定义体
private: 
 int x; 
}; 
 
class Y: public X { 
private: 
 int y; 
}; 
 
int main(){ 
 X* x = new Y; 
 delete x;

2.= delete

2.1 引入背景

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

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; 
}; 

使用“=delete”来限制函数生成

2.2.1 规则

(1) 必须在函数第一次声明的时候将其声明为 deleted 函数
(2) 不同于default,delete没有限制为特殊成员函数才能使用delete

3. boost中的使用

在支持C++11标准下,noncopyable类定义如下:

class noncopyable {
    protected:
        noncopyable() = default;
        ~noncopyable() = defalult;

        noncopyable(const noncopyable& );
        noncopyable& operator= (const noncopyable&);
};

参考资料:
https://www.jianshu.com/p/ef66ba66916c
https://blog.csdn.net/lixiaogang_theanswer/article/details/81090622
https://www.cnblogs.com/lsgxeva/p/7787438.html

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++11中的delete和=default关键字与C++98标准的delete和=default有些不同,下分别介绍: 1. deleteC++11中,delete关键字不仅可以用于销毁new出来的对象,还可以用于显式地禁用某些函数,例如: ``` class MyClass { public: MyClass(int x) { // 构造函数 } MyClass(const MyClass&) = delete; // 禁用复制构造函数 MyClass& operator=(const MyClass&) = delete; // 禁用复制赋值运算符 }; ``` 上面的代码中,禁用了复制构造函数和复制赋值运算符,这样就可以避免对象的浅拷贝问题。如果需要复制对象,可以手动编写复制函数。 2. =defaultC++11中,=default关键字用于显式地生成默认函数,例如: ``` class MyClass { public: MyClass() = default; // 显式地生成默认构造函数 MyClass(const MyClass& other) = default; // 显式地生成复制构造函数 MyClass& operator=(const MyClass& other) = default; // 显式地生成复制赋值运算符 ~MyClass() = default; // 显式地生成析构函数 }; ``` 需要注意的是,使用=default来生成默认函数时,需要保证该函数是可以编译通过的,否则会导致编译错误。如果一个类中的某个函数被显式地声明为=default,那么编译器会自动为该函数生成默认实现。默认实现的行为与编译器自动生成的默认函数相同。另外,如果一个类中的某个函数被显式地声明为=default,则该函数不能被重载。 总之,C++11中的delete和=default关键字扩展了它们的用途,使得程序员可以更加灵活地控制对象的行为。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值