TheRiver | blog

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

0%

特殊成员函数

要点

num 1

  • 移动构造(赋值)函数,也会调用其基类的移动构造(赋值)函数(如果有的话);
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
#include <iostream>

using namespace std;

class base {
public:
base() = default;
base(base &){
cout << "base: copy constructor" << endl;
}
base(base &&) noexcept{
cout << "base: move constructor" << endl;
}
};
class derived:public base {
public:
derived() = default;
derived(derived & param):base(param){
cout << "derived: copy constructor" << endl;
}
derived(derived && param) noexcept :base(std::move(param)){
cout << "derived: move constructor" << endl;
}
};
int main()
{
derived c;
derived d = c;

derived e = std::move(c);
return 0;
}

//output
//base: copy constructor
//derived: copy constructor
//base: move constructor
//derived: move constructor

num 2

  • 按成员移动是分两部分组成的,一部分是在支持移动操作的成员上执行的移动操作,另一部分是在不支持移动操作的成员上执行的复制操作

num 3

  • 即使声明了复制构造/赋值操作符 函数的其中一个,当代码实现需要另一个的时候,编译期也会默认实现另一个(c++11称之为被废弃的行为)
  • 如果声明了移动构造/赋值操作符 函数的其中一个,即使代码需要另一个的时候,编译期也不会默认实现另一个
  • 如果声明了复制构造/赋值运算符函数,则不会生成默认的移动构造/移动赋值运算符函数。
  • 如果声明了移动构造/移动赋值运算符函数,则不会声明默认的复制构造/赋值运算符函数。
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
#include <iostream>

using namespace std;

class cc {
public:
cc() = default;
cc(cc & ) {
cout << "copy construct" << endl;
}
};

class dd {
public:
dd() = default;
dd(dd &&) noexcept{
cout << "move construct" << endl;
}
};
int main()
{
cc data;
data = cc(); //no output

dd data2;
//note: ‘dd& dd::operator=(const dd&)’ is implicitly declared as deleted because ‘dd’
// declares a move constructor or move assignment operator
data2 = std::move(dd());
return 0;
}

num 4

  • 如果声明了析构函数,复制构造和赋值操作符函数也会生成(c++11称之为被废弃的行为)
  • 如果声明了析构函数,移动函数都不会生成
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
#include <iostream>

using namespace std;

class cc {
public:
cc() = default;
~cc() {
cout << "destructor" << endl;
}
};

class dd {
public:
dd() = default;
~dd() {
cout << "destructor" << endl;
}
};
int main()
{
cc data;
data = cc();

dd data2 = std::move(dd()); //const & 拷贝构造函数

return 0;
}

num 5

  • 如果声明了构造函数/赋值运算符函数 的一种实现,则不再生成默认的实现
  • 如果声明了基本构造函数,不会影响默认生成其他拷贝构造函数
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
class cc {
public:
cc(cc &) {
cout << "constructor" << endl;
}
};

int main()
{
cc data; //error: no matching function for call to ‘cc::cc()’

return 0;
}

class cc {
public:
cc() {
cout << "constructor" << endl;
}
};

int main()
{
cc data = std::move(cc()); //ok
return 0;
}

num 6

  • c++11中析构函数默认都是noexcept

num 7

  • 模板拷贝构造函数,赋值运算符函数,不会阻止默认函数的实现
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 <iostream>

using namespace std;

class cc {
public:
template<typename T>
cc(const T &)
{

}

template<typename T>
cc& operator=(const T &)
{

}

};

int main()
{
cc data = cc(); //模板成员函数会阻止默认构造函数生成
//但不会阻止默认拷贝/默认赋值操作符函数的生成
return 0;
}

ending

2020071502.jpg

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