面试之快速学习C++11 - 右值 移动构造 std::move

C++11右值引用

  1. 字面意思,以引用传递的方式使用c++右值
  2. 左值和右值,左值是lvalue loactor value 存储在内存中,有明确存储地址的数据, 右值rvalue read value , 指的是那些可以提供数据值的数据(不一定可以寻址, 例如存储于寄存器中的数据)
  3. 怎么去判读:
  • 可位于赋值号 左侧的表达式就是左值,位于赋值号右侧的就是右值
    如:
int b = 10;
5 = a; //error
  • 有名称的,可以获取到存储地址的表达式即为左值,反之是右值,左值也可以是右值

C++11 新特性:移动构造函数和std::move

void testMoveFunction (){
   string str1 = "ok";
   string str2 = str1;
   
   cout<< "str1 :"<<str1 <<endl;
   cout<< "str2 :"<<str2 <<endl;
   
   string str3 = "ok";
   string str4 = move(str3);
   
   cout<< "str3 :"<<str3 <<endl;
   cout<< "str4 :"<<str4 <<endl;
   
   /*
    str1 :ok
    str2 :ok
    str3 :
    str4 :ok
    */
}

  1. 移动构造函数,将str3强制转化为右值,将内存中的值放到寄存器没,然后再将寄存器的值放到内存str4的位置。
class TestCopyConstruct {
public:
   TestCopyConstruct():num(new int(0)){
       cout<<"defalut TestCopyConstruct constructor !" << endl;
   }
   TestCopyConstruct(const TestCopyConstruct &d):num(new int(*d.num)){
       cout<<"copy TestCopyConstruct constructor !"<< endl;
   }
   //模拟的移动构造方法
   TestCopyConstruct(TestCopyConstruct &&d):num(d.num) {
       d.num = NULL;
       cout<<"move TestCopyConstruct constructor !"<< endl;
   }
   ~TestCopyConstruct(){
       cout<<"destruct TestCopyConstruct !"<< endl;
   }
private:
   int *num;
};
TestCopyConstruct testTestCopyConstruct() {
    TestCopyConstruct a = TestCopyConstruct();
    //TestCopyConstruct b = std::move(a); 注意这里不会掉用移动拷贝构造函数!
    TestCopyConstruct b(std::move(a));
    return b;

}
  1. 自己理解: 把一个值的托管权交给了另一个主人,所以你一定要注意在构造移动构造函数时,旧主人的值要清理!
  2. 一个比较喜欢的答案:
    std::move没干任何事,就只是把变量的名字藏起来了。
    然后这个对象就变成了匿名对象,你就可以调用接收右值的重载函数了。具体这个函数要干什么……你想干什么就干什么.
  3. 突然觉得也需要理解一下引用: https://blog.csdn.net/ifwecande/article/details/108684300
    有一个地方可以关注一下,引用第一次赋值之后就不能修改了
int a = 9;
int &b = a

实际上在b引用a之后,后面所看到的b都是*(&a)所以无法赋值。
好吧好吧和这次的内容关系不大~

6.当右值去初始化一个对象的时候,那么会优先调用移动构造函数,那么如果想用左值初始化,就需要move()方法了

  1. 注意有一个问题:C++move操作过后对象本身到底是否为空?这里清空不清空并不是std::move()决定的。其实是在你把它当作右值进行赋值时,类的移动构造函数决定的,比如前面的
TestCopyConstruct(TestCopyConstruct &&d):num(d.num) {
     d.num = NULL;
     cout<<"move TestCopyConstruct constructor !"<< endl;
 }

你会在拷贝完右值之后,把他的指针 d.num = NULL;
比如下面的代码:

 int a2 = 999;
 int &&b = std::move(a2);
 int c = a2;
 c = 777;
 
 //a2还为999
 
 string a3 = "3333";
 string b3 = std::move(a3);
 string c4 = a3;
 //a3为""了,取决于string的移动拷贝构造
 */

前面写的很乱,想总结一下

  1. 移动构造其实只是自己实现的一种拷贝构造方式,其内部实现其实是交给创建类的 “作者”
  2. std::move更像是一种指引,告诉你需要调用移动构造函数,并且心理上暗示“这个值不能用了”
  3. 而作为作者,防止旧的值还会用,那么你需要在移动构造中给旧值恢复默认值

你可能感兴趣的:(面试之快速学习C++11,面试,学习,c++)