zoukankan      html  css  js  c++  java
  • [85] 左值右值(移动语义前篇)

    左值和右值(L值和R值)

    基础概念

    int RGetValue()
    {
    	return 10;
    }
    int& LGetValue()
    {
    	static int value = 10;
    	return value;
    }
    int main()
    {
    	//1.很多时候就像这个,左值就好像是在等号的左边
    	//右值在等号的右边,但这并不是一个完整的事实(实际上也不是这样)
    	//在这个例子中,i在内存中有地址,而10只是一个值,没有存储空间,直到它分配给L值
    	//所以,你不能给R值赋值。
    	int i = 10;
    	
    	//2.这俩个a,和i都是左值。
    	int a = i;
    
    	//3.在这个例子中,RGetValue返回的也是一个R值,因为即使返回一个int,它在内存中也没有位置。
    	//在这里我们做的是,获得一个右值,将该临时值赋值并存储为L值。
    	int i = RGetValue();
    	
    	//在这个例子中,我们在函数返回的就是一个左值了,(我们定义了一个静态的函数对象的引用并返回)
    	LGetValue() = 5;
    }
    

    关于引用

    1、左右值都可以做参数

    void SetValue(int value)
    {
    
    }
    
    int main()
    {
    	int i = 10;
    	//在这个带参数的例子中,我们可以用L值做参数,也可以用R值做参数
    	//但是在用R值做参数的情况下,当函数实际被调用时,这个R值将会被用来创建L值
    	SetValue(i);
    	SetValue(10);
    }
    

    2、左值参考

    void SetValue(int& value)
    {
    
    }
    
    int main()
    {
    	int i = 10;
    	//一旦调用函数的参数是一个左值引用,这里就会立即出现一个错误
    	SetValue(10);
    }
    

    在这个错误提示中,有一个很特殊的规则,就是const。
    当我们试图写int& a = 10;,这是不被允许的,但是如果我们写const int&a = 10;,这样就可行了。这个特殊的规则实际上编译器做的事情可能就像是

    	int temp = 10;
    	const int& a = temp;
    

    实际上这只是避免去创建一个L值,而是仅仅能都支持L值和R值
    所以如果我们想让开始的左值引用代码生效,我们可以这样改动它

    //注意,我们在这里让参数等于const int&
    void SetValue(const int& value)
    {
    
    }
    int main()
    {
    	int i = 10;
    	//这样就都支持了!
            SetValue(i);
    	SetValue(10);
    }
    

    3、右值引用
    如果我们想写一个仅接受临时对象的函数呢,我们就需要所谓右值引用&&了!

    void PrintName(std::string&& name)
    {
    	std::cout << name << std::endl;
    }
    
    int main()
    {
    	std::string firstName = "Yan";
    	std::string lastName = "Chernikov";	
    	std::string fullName = firstName + lastName;
    
    	PrintName(firstName);
    }
    


    这是有意义的,因为我们可以编写此函数的重载

    void PrintName(const std::string& name)
    {
    	std::cout << "[lvalue]" << name << std::endl;
    }
    void PrintName(std::string&& name)
    {
    	std::cout << "[rvalue]" << name << std::endl;
    }
    
    int main()
    {
    	std::string firstName = "Yan";
    	std::string lastName = "Chernikov";
    	
    	std::string fullName = firstName + lastName;
    
    	PrintName(fullName);
    	PrintName(firstName + lastName);
    }
    


    这非常有用,不过是在另一个主题“移动语义”上啦。

  • 相关阅读:
    手把手实战:eclipse 搭建 SpringMvc 框架环境
    解决eclipse中Tomcat服务器的server location选项不能修改的问题
    如何解决JSP页面顶端报错 The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
    第二课 --- git的(管理修改和撤销修改、删除文件)
    第二课 ---git时光穿梭(版本回退)
    第一课——git的简介和基本使用
    001——使用composer安装ThinkPHP5
    微信小程序中对于变量的定义
    微信小程序onLaunch修改globalData的值
    7——ThinkPhp中的响应和重定向:
  • 原文地址:https://www.cnblogs.com/EvansPudding/p/12726823.html
Copyright © 2011-2022 走看看