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);
    }
    


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

  • 相关阅读:
    dotnet core 获取 MacAddress 地址方法
    dotnet core 获取 MacAddress 地址方法
    dotnet core 发布只带必要的依赖文件
    dotnet core 发布只带必要的依赖文件
    Developing Universal Windows Apps 开发UWA应用 问答
    Developing Universal Windows Apps 开发UWA应用 问答
    cmd 如何跨驱动器移动文件夹
    cmd 如何跨驱动器移动文件夹
    C++ 驱动开发 error LNK2019
    C++ 驱动开发 error LNK2019
  • 原文地址:https://www.cnblogs.com/EvansPudding/p/12726823.html
Copyright © 2011-2022 走看看