0%

C++11 中的默认函数控制 delete 和 default

delete 和 default 在 C++ 中用于显式控制默认函数的生成情况, 我们需要知道 C++ 编译器到底干了些什么

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <string>
#include <vector>
#include <map>

//c++11 类默认函数的控制:"=default" 和 "=delete"函数

/*
C++ 的类有四类特殊成员函数, 它们分别是:默认构造函数、析构函数、拷贝构造函数以及拷贝赋值运算符.
这些类的特殊成员函数负责创建、初始化、销毁, 或者拷贝类的对象.
如果程序员没有显式地为一个类定义某个特殊成员函数, 而又需要用到该特殊成员函数时, 则编译器会隐式的为这个类生成一个默认的特殊成员函数.
*/

// C++11 标准引入了一个新特性:"=default"函数. 程序员只需在函数声明后加上“=default;”, 就可将该函数声明为 "=default"函数, 编译器将为显式声明的 "=default"函数自动生成函数体.
class X
{
public:
X() = default; //该函数比用户自己定义的默认构造函数获得更高的代码效率
X(int i)
{
a = i;
}

private:
int a;
};

X obj;

// "=default"函数特性仅适用于类的特殊成员函数, 且该特殊成员函数没有默认参数.
class X1
{
public:
int f() = default; // err , 函数 f() 非类 X 的特殊成员函数
X1(int, int) = default; // err , 构造函数 X1(int, int) 非 X 的特殊成员函数
X1(int = 1) = default; // err , 默认构造函数 X1(int=1) 含有默认参数
};

// "=default"函数既可以在类体里(inline)定义, 也可以在类体外(out-of-line)定义.
class X2
{
public:
X2() = default; //Inline defaulted 默认构造函数
X2(const X&);
X2& operator = (const X&);
~X2() = default; //Inline defaulted 析构函数
};

X2::X2(const X&) = default; //Out-of-line defaulted 拷贝构造函数
X2& X2::operator= (const X2&) = default; //Out-of-line defaulted 拷贝赋值操作符


// 为了能够让程序员显式的禁用某个函数, C++11 标准引入了一个新特性:"=delete"函数. 程序员只需在函数声明后上“=delete;”, 就可将该函数禁用.
class X3
{
public:
X3();
X3(const X3&) = delete; // 声明拷贝构造函数为 deleted 函数
X3& operator = (const X3 &) = delete; // 声明拷贝赋值操作符为 deleted 函数
};

// "=delete"函数特性还可用于禁用类的某些转换构造函数, 从而避免不期望的类型转换
class X4
{
public:
X4(double)
{

}

X4(int) = delete;
};

// "=delete"函数特性还可以用来禁用某些用户自定义的类的 new 操作符, 从而避免在自由存储区创建类的对象
class X5
{
public:
void *operator new(size_t) = delete;
void *operator new[](size_t) = delete;
};


void mytest()
{
X4 obj1;
X4 obj2=obj1; // 错误, 拷贝构造函数被禁用

X4 obj3;
obj3=obj1; // 错误, 拷贝赋值操作符被禁用

X5 *pa = new X5; // 错误, new 操作符被禁用
X5 *pb = new X5[10]; // 错误, new[] 操作符被禁用

return;
}


int main()
{
mytest();

system("pause");
return 0;
}