C++11为什么引入移动构造函数和右值引用?
-
class
Student { -
private
: -
int
*
numID ; -
public
: -
Student():
numID
(
new
int
(
0
))
{ -
cout <<
“construct!”
<<
endl ; - }
- //深层拷贝构造函数
-
Student(
const
Student &
d ):
numID
(
new
int
(*
d .
numID ))
{ -
cout <<
“copy construct!”
<<
endl ; - }
- //添加移动构造函数
-
Student(Student
&&
d ):
numID
(
d .
numID )
{ -
d .
numID =
nullptr ; -
cout <<
“move construct!”
<<
endl ; - }
-
~Student
()
{ -
cout <<
“class destruct!”
<<
endl ; - }
-
}
;
上面一个Student类, 实现了一个拷贝构造函数(深层拷贝)和移动构造函数。我们发现移动构造函数其实执行的浅层拷贝,只不过多了将numID置空的操作,那么现在真正的问题来了,那我直接写一个浅层的拷贝构造函数, 再加一个numID置空的操作不就可以了吗?
- //错误的浅层拷贝
-
Student(const Student
&
d ):
numID
(
d .
num )
{ -
d .
numID =
nullptr ;//此句不能编译通过 -
cout <<
“move construct!”
<<
endl ; - }
理想很丰满,现实是这是错误的。d 由const 修饰,那么numID 是不能修改的。到这里有人想到,那去掉const 不就可以了吗?wow, 确实,我也是这么想的。也就是说可以如下写:
#include
using namespace std;
class Student{
private:
int *numID;
public:
Student():numID(new int(0)){
cout<<"construct!"<<endl;
}
//深层拷贝构造函数
Student(const Student &d):numID(new int(*d.numID)){
cout<<"copy construct!"<<endl;
}
//添加移动构造函数
Student(Student &&d):numID(d.numID){
d.numID =nullptr;
cout<<"move construct!"<<endl;
}
//
Student(Student &d):numID(d.numID){
d.numID =nullptr;
cout<<"false copy construct!"<<endl;
}
~Student(){
cout<<"class destruct!"<<endl;
}
};
int main()
{
const Student s;//
Student ss(s);
return 0;
}
这样确实可以解决指针悬挂问题,也类似移动构造函数,那为什么C++11要大费周章的引入移动构造和右值引用??
看如下代码:
Student(int &d){
numID = &d;
}
//main
Student(10);//error
非常量的左值引用和右值不能绑定,这也就说明不加const不能接收右值。
值得注意的地方:右值短暂,左值持久。也就是右值引用只能绑定到临时对象,该对象在后续代码中没有任何作用。
结合起来也就明白为什么要引入右值引用&&这个新类型和移动构造函数,移动构造是为右值而生的,也就是为临时对象而生的(当然左值可以通过std::move()转换右值,避免深层拷贝)。临时对象是在后续代码中没有用的,因此可以将指针置空。而自己写的去掉const 的“拷贝构造”是不能接收右值的,这样就很没意义。