c++关键字: =delete和=default

=delete

概述 

=delete关键字是c++11新增的关键字,主要用于的场景是:当我们不希望类中的函数被类对象在外部调用的时候,我们就可以使用这个关键字。

其实,之前我们实现这种功能是将这些函数放在private修饰符下,但是这种方法是依靠语法特性来实现的,有些地方可能并不合适。


举个例子:   使用private虽然在类外不能使用这些函数了,但是在类的内部还是可以使用的,但是我们目前的要求是在任何地方都不能使用这些函数,那么这时候就得使用=delete关键字了。(因为用来它之后就相当于删除了,自然哪里也用不了了)

疑问:  那我们不用直接将这些函数删除不就好了,为什么多次一举呢?  

对于普通的函数,我们直接删除了自然时最好的,也可以减少歧义。

但是对于类的构造函数呢? 即使我们删除了,编译器也会自己给我们创建一个,这样即使我们删除掉,最起码在类内部还时可以使用的,所以这时候我们就得使用=delete关键字了。

使用=delete修饰类的构造函数之后,编译器就不会自动提供了,而且编译器依然会认为它们被删除了无法使用。

1. 此关键字用于构造函数 

对于构造函数,无论隐式的(就是编译器自己提供的)还是显示的(我们自己写的),在创建实例对象的时候,编译器都会默认去调用这些函数。但是有些时候,我们并不希望外界使用我们这些函数,那么就可以使用=delete关键字修饰,这样就相当于删除了对应的构造函数

代码例子:   

c++中有四种构造函数: 默认构造,有参构造,拷贝构造,赋值构造(=运算符重载)

#include <iostream>
#include <stdlib.h>

using namespace std;

class A {
public:
	A() = delete;
	A(const A& a) = delete;
	A(int a) = delete;
	A& operator=(const A& a) = delete;
};

int main(void) {
	A a;  // 错误:  无法引用 "A" 的默认构造函数 -- 它是已删除的函数

	system("pause");
	return 0;
}

上面的代码,我们对类A中的所以构造函数都使用了=delete关键字。我们在main函数中创建对象a,会报错,因为创建对象会调用默认构造函数,但是我们使用=delete关键字修饰了默认构造函数,就相当于它被删除了,会报错。(其它的构造函数也一样,可以自己尝试)

一般情况下,我们是不会将所有的构造函数都用=delete(除非你这个类不常见对象),否则,建议只是根据需要将对应的构造函数=delete即可。

比如,将拷贝构造函数和复制构造函数用哪个delete修饰,不允许对类对象进行拷贝了,但是可以使用默认构造函数创建对象。(当然根据具体需要来选择)

2. 此关键字用于普通成员函数 

其实用于普通成员函数,也是一样的道理,编译器会认为这个函数删除了,但是成员函数和构造函数不一样,我们为什么不直接将其删除了,反正也不用了,何必多此一举。

当然,有一种情况下也是可以使用的   --  避免传参时进行形式转换。

一般情况,参数传递的时候,编译器都会进行隐式转换比如:

#include <iostream>
#include <stdlib.h>

using namespace std;

class A {
public:
	void func(int a) {
		printf("%d\n", a);
	}
};

int main(void) {
	A a; 
	a.func(1.2);   // 打印结果为1

	system("pause");
	return 0;
}

上面,我们给函数func传入一个double的值1.2,但是func的参数类型为int型,所以传入之后进行了隐式转换,将double的1.2转化为了int的1。

 下面代码就可以避免这种隐式转换

#include <iostream>
#include <stdlib.h>

using namespace std;

class A {
public:
	void func(int a) {
		printf("%d\n", a);
	}
	void func(double a) = delete;
};

int main(void) {
	A a; 
	a.func(1.2);   // 出错

	system("pause");
	return 0;
}

其实我们使用函数重载就可以避免,也就是我们在传入double的值调用的是形参为double的函数,这样就避免了。

但是,如果我们不希望外界使用形参为double的函数,还要避免隐式转换,就可以使用上面这种方式,我们直接传入double的值,就不会隐式转换而是直接报错了。

3. 一般情况下,此关键字不要修饰析构函数 

因为如果使用=delete修饰析构函数,那么我们创建的对象就无法释放了。会一直占用空间。因为释放对象,是需要调用析构函数的。 

=default 

概述 

default就是默认的意思,这个关键字用来修饰构造函数,告诉编译器给函数实现默认的实现。
其实就是给指定函数实现对应默认的代码,适当的使用可以提高代码效率和可读性。

只能用于默认构造,拷贝构造,赋值构造和析构, -- 因为这些函数我们不写,编译器也会替我们写(编译器知道默认怎么写),=default关键字就是让编译器替我们写函数的实现,前提是编译器知道怎么写才行。(也就是默认构造,拷贝构造,赋值构造和析构才行)

当然,如果函数中需要实现我们想要的功能(比如,开辟空间,释放空间等),或者说有函数实现,就不能使用=default来修饰。

如果在类内部给对应函数添加=default,那么其实现的函数是内联的,如果不希望是内联的那就在类外部进行指定=default。

代码例子: 
class A {
public:
	A() = default;
	A(const A& a) = default;
	A& operator=(const A& a) = default;
    ~A() = default;
};

  • 21
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++11中的=delete和=default是两个C++关键字,它们都用于显式地声明或定义类的特殊成员函数。下面分别进行详细介绍: 1. =deleteC++11中,=delete关键字用于显式地禁用某些函数。例如,可以使用=delete关键字来禁用一个类的拷贝构造函数和拷贝赋值运算符,从而避免对象的浅拷贝问题,例如: ``` class MyClass { public: MyClass(int x) { // 构造函数 } MyClass(const MyClass&) = delete; // 禁用拷贝构造函数 MyClass& operator=(const MyClass&) = delete; // 禁用拷贝赋值运算符 }; ``` 在上述代码中,使用=delete关键字禁用了拷贝构造函数和拷贝赋值运算符,这样就可以避免对象的浅拷贝问题。如果需要拷贝对象,可以手动编写拷贝函数。 需要注意的是,使用=delete关键字声明函数时,该函数不能被调用,否则会在编译时产生错误。 2. =defaultC++11中,=default关键字用于显式地定义默认函数。例如,可以使用=default关键字来显式地定义一个类的默认构造函数、拷贝构造函数、拷贝赋值运算符和析构函数,例如: ``` class MyClass { public: MyClass() = default; // 显式地定义默认构造函数 MyClass(const MyClass&) = default; // 显式地定义拷贝构造函数 MyClass& operator=(const MyClass&) = default; // 显式地定义拷贝赋值运算符 ~MyClass() = default; // 显式地定义析构函数 }; ``` 需要注意的是,使用=default关键字定义函数时,该函数的实现必须符合默认函数的行为,否则会在编译时产生错误。 总之,C++11中的=delete和=default关键字扩展了它们的用途,使得程序员可以更加灵活地控制对象的行为。同时,它们也提高了程序的可读性和可维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值