1.节约资源
通过上一次讲解,我们发现程序做了很多无意义的拷贝,如果能直接将那些要销毁的元素直接给新的元素,那不省去了很多事情吗?
没错C++11的移动语义,就是干这个事情的
2.C++11
①createAndInsert(); 函数
#include <string>
#include <vector>
std::vector<std::string> createAndInsert()
{
std::vector<std::string> coll; //创建了一个vector 里面的元素是string
coll.reserve(3); // 在堆中预留了三个位置
std::string s = "data"; // 创建了字符串对象s
coll.push_back(s); // 插入string对象
coll.push_back(s+s); // 插入临时对象string
coll.push_back(std::move(s));
//插入了一个我们不在需要的字符串s
return coll; // return vector of strings
}
②main函数 没有发生变化
int main()
{
std::vector<std::string> v; // create empty vector of strings
...
v = createAndInsert(); // assign returned vector of strings
...
}
我们看看哪里产生了优化?
①coll.push_back(s+s);
s+s会产生一个新的临时对象Temp,Temp是一个右值,下来怎么做?
不进行深拷贝了,直接把这个Temp指向的字符串拿过来,move过来,
Temp现在不指向它原有的字符串了,指向nullptr
然后Temp这个变量被销毁了
②coll.push_back(std::move(s));
在这个语句之后,我们再也没有用到s了,所以在函数结束之后,他会被析构,std::move就代表I no longer need this value here.
所以coll的第三个元素指向了s的字符串,没有进行深拷贝
③return coll;
在启用命名返回值优化的前提下(也就是不会产生一个右值),,直接move coll的字符串,给v
3.注意
①std::move(s) 仅仅标志着 这个是可以被移动的,并没有真正产生移动
string s{ "123" };
std::move(s);
cout << s << endl;
输出的结果仍然是123
②在真正的进行move后,s的值是未定义的,取决于编译器
vector<string> v;
string s{ "123" };
v.push_back(std::move(s));
s.append("456");
cout << s << endl;
输出的结果是456 VS2019的测试