C++温故补缺(五):移动构造函数
移动构造函数[C11新增]
参考:知乎:C++11右值引用和移动构造函数详解.知乎:什么是POD数据类型.
C++ 11之前,对象的拷贝由三个函数决定:拷贝构造函数,拷贝赋值运算符和析构函数。
C++ 11新增两个函数:移动构造函数和移动赋值运算符。
首先介绍移动语义(move),指以移动的方式而非深拷贝的方式初始化含有指针成员的类对象。也就是剥夺了用于初始化的对象的资源。
如:使用std::move()函数来初始化对象
#include<iostream>
using namespace std;
int main(){
string str="hello";
string ss=move(str);
cout<<"str:"<<str<<endl<<"ss:"<<ss<<endl;
}
可以看到str字符串变为空了,也就是移动而非拷贝的方式初始化ss。
move
move在Cplusplus中的解释是:
std::move
is used to indicate that an objectt
may be "moved from", i.e. allowing the efficient transfer of resources fromt
to another object.In particular,
std::move
produces an xvalue expression that identifies its argumentt
. It is exactly equivalent to astatic_cast
to an rvalue reference type.
move函数是用于对象之间高效地转移资源的。也就是前面说的move语义,剥夺而非拷贝的方式获取资源。特别,move函数可以生成一个和它的参数t有关联的xvalue(指资源可以再利用的对象)表达式。也就是move会返回和参数类型相同的类型的表达式。完全等同于static_cast强制转换右值引用类型。
对于no-pod类型,move是以移动的方式获取资源,而pod类型,则是直接复制。并不会有参数的资源销毁。
pod类型是plain old data的缩写,指没有构造/析枸函数、复制/移动构造函数、复制/移动运算符的的数据类型。如int,char,float等。
而no-pod就是有这些东西的,如string,以及自定义的类
如:直接move()一个int
#include<iostream>
using namespace std;
int main(){
int a=10;
int b=move(a);
cout<<"a:"<<a<<" b:"<<b;
}
,move就并不会销毁a中的资源
再比如:没有定义移动构造函数的类的对象用move初始化
#include<iostream>
using namespace std;
class A{
public:
char *c;
A(string s){
this->c=&s[0];
}
};
int main(){
A a1("hello");
A a2=move(a1);
cout<<a2.c<<endl;
cout<<a1.c;
}
,move也没有销毁参数的资源
所以是需要我们自己定义销毁行为的
#include<iostream>
using namespace std;
class A{
public:
char *c;
A(string s){
this->c=&s[0];
}
A(A &&temp){
this->c=temp.c;
temp.c=nullptr;
}
};
int main(){
A a1("hello");
A a2=move(a1);
cout<<a2.c<<endl;
cout<<a1.c;
}
,这样就实现了移动。
为什么要销毁?
一般认为,移动资源后,原来的参数就不会再被访问到,为了保证这一点,需要手动置零/置空/释放内存,这也是对前面"高效"的解释。
本文来自博客园,作者:Tenerome,转载请注明原文链接:https://www.cnblogs.com/Tenerome/p/cppreview5.html