TheRiver | blog

You have reached the world's edge, none but devils play past here

0%

c++11-delete_default

参考

C++11 标准新特性:Defaulted 和 Deleted 函数

delete

c++的特殊成员函数:默认构造函数,默认拷贝构造函数,默认赋值操作符重载函数,默认析构函数。如果程序没有自己实现这些函数,但代码中需要用到的话,编译器会自己实现这些函数。有的时候不想要编译器自己实现,比如不希望有默认的拷贝构造和赋值操作符重载,就可以这样:

1
2
3
4
5
6
7
8
9
10
class myclass
{
int _m;
private:
myclass();
~myclass();
myclass(const myclass & param);
myclass & operator=(myclass & param);
};

将拷贝构造函数和赋值操作符重载函数作为private,并且只声明而不实现,这样就避免了编译器自动生成,而自己又不必去实现。而c++11引入了delete关键字,使用如下:

1
2
3
4
5
6
7
8
9
10
class myclass
{
int _m;
private:
myclass() = delete;
~myclass() = delete;
myclass(const myclass & param) = delete;
myclass & operator=(myclass & param) = delete;
};

这样带delete关键字的函数是不能被调用的,表示该函数被禁用。

注意:

  • delete关键字可以用在类内,也可以用在类外。
  • 并且delete函数也可以用在普通函数上,不一定是类的成员函数:
1
2
3
4
5
6
7
void func(void) = delete;

int main()
{
func();
std::cout << "Hello World!\n";
}
错误(活动)    E1776    无法引用 函数 "func()" (已声明 所在行数:15) -- 它是已删除的函数    

delete也可以用于限制一些特定的函数类型参数对应的函数实现,具体如下:

1
2
3
4
5
6
7
8
9
10
void func(int param)
{
cout << param << endl;
}

int main() {
func(true); //1
func(1.2); //1
func('a'); //97
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void func(int param)
{
cout << param << endl;
}

void func(bool param) = delete;
void func(double param) = delete;
void func(char param) = delete;

int main() {
func(true); //无法引用 函数 "func(bool param)" (已声明 所在行数:12) -- 它是已删除的
float f = 1.2; //float-->double
func(f); //无法引用 函数 "func(double param)" (已声明 所在行数:13) -- 它是已删除
func('a'); //无法引用 函数 "func(char param)" (已声明 所在行数:14) -- 它是已删除的
func(1);
}

c++98版本的策略对于类的模板函数不能生效:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
using namespace std;

class myclass
{
public:
template <typename T>
void func(T param)
{
cout << param << endl;
}

//private:
template <typename T>
//void func<int>(int param); //编译不过
void func(int param); //还是会调用模板函数,相当于没生效
};

int main() {

myclass m;
char c = 'c';
m.func(c);

int i = 10;
m.func(i);
}

default

还有一种情况,默认的这几个函数,如果代码中自己实现了,则编译器不会自己再去实现了。但有些时候希望用到默认的编译器可以自己实现的函数,因为这样不用自己写起来麻烦,并且编译器自己实现的函数性能比自己实现的要高:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class myclass
{
int _m;
public:
myclass(int n):_m(n)
{

}

};


int main()
{
myclass a;
return 0;
}

错误(活动) E0291 类 “myclass” 不存在默认构造函数 ConsoleApplication6

自己实现了带参数的构造函数,编译器不会再去自己实现无参构造函数了,可以这样:

1 带缺省参数的构造函数

1
2
3
4
5
6
public:
myclass(int n = 0):_m(n)
{

}

2 另外实现无参构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class myclass
{
int _m;
public:
myclass(int n):_m(n)
{

}

myclass()
{

}

};

int main()
{
myclass a;
return 0;
}

3 什么构造函数都不实现,让编译器去实现默认的构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

#include "pch.h"
#include <iostream>

class myclass
{
int _m;
public:
//myclass(int n):_m(n)
//{

//}

//myclass()
//{

//}

};

int main()
{
myclass a;
return 0;
}

4 根据需求这个类需要另外实现其他的构造函数,还想要使用编译器自己实现的构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class myclass
{
int _m;
public:
myclass(int n):_m(n)
{

}

myclass() = default;

};

int main()
{
myclass a;
return 0;
}

default关键字可以让编译器去实现默认的函数

注意点:

  • 只针对于这几种:默认构造函数,默认析构函数,拷贝/移动构造函数,赋值/移动赋值操作符重载函数。
  • 不可用于类外
  • default的函数由编译器自己实现函数体,性能比自己写的性能要高
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class myclass
{
int _m;
public:
myclass(int n):_m(n)
{

}

myclass() = default;

};

void func(void) = default;

int main()
{
myclass a;
return 0;
}

错误(活动) E1774 “= default”只能出现在默认构造函数、复制/移动构造函数、复制/移动赋值运算符和析构函数中

ending

82747100_p0_master1200_lit.jpg

----------- ending -----------