首页 > 其他分享 >左值 <->右值

左值 <->右值

时间:2024-09-24 15:35:49浏览次数:1  
标签:std 右值 int 左值 引用 ref

左值引用指向左值

右值引用指向右值

int a = 5;
int &ref_a = a; // 左值引用指向左值,编译通过
int &ref_a = 5; // 左值引用指向了右值,会编译失败

int &&ref_a_right = 5; // ok
int a = 5;
int &&ref_a_left = a; // 编译不过,右值引用不可以指向左值
 
ref_a_right = 6; // 右值引用的用途:可以修改右值

引用是变量的别名,由于右值没有地址,没法被修改,所以左值引用无法指向右值。

右值引用专门为右值而生,可以指向右值,不能指向左值

左值引用指向右值(特殊)

但是,const左值引用是可以指向右值的:

const int &ref_a = 5;  // 编译通过

const左值引用不会修改指向值,因此可以指向右值,这也是为什么要使用const &作为函数参数的原因之一,

如std::vector的push_back:

void push_back (const value_type& val);

如果没有const,vec.push_back(5)这样的代码就无法编译通过了。

右值引用指向左值(特殊)

有办法,std::move:

int a = 5; // a是个左值
int &ref_a_left = a; // 左值引用指向左值
int &&ref_a_right = std::move(a); // 通过std::move将左值转化为右值,可以被右值引用指向
cout << a; // 打印结果:5

在上边的代码里,看上去是左值a通过std::move移动到了右值ref_a_right中,那是不是a里边就没有值了?并不是,打印出a的值仍然是5。

std::move是一个非常有迷惑性的函数,不理解左右值概念的人们往往以为它能把一个变量里的内容移动到另一个变量,

但事实上std::move移动不了什么,唯一的功能是把左值强制转化为右值,

让右值引用可以指向左值。其实现等同于一个类型转换:static_cast<T&&>(lvalue)。

所以,单纯的std::move(xxx)不会有性能提升,std::move的使用场景在第三章会讲。

左值引用、右值引用本身是左值

被声明出来的左、右值引用都是左值。 因为被声明出的左右值引用是有地址的,也位于等号左边。

仔细看下边代码:

// 形参是个右值引用
void change(int&& right_value) {
    right_value = 8;
}
 
int main() {
    int a = 5; // a是个左值
    int &ref_a_left = a; // ref_a_left是个左值引用
    int &&ref_a_right = std::move(a); // ref_a_right是个右值引用
 
    change(a); // 编译不过,a是左值,change参数要求右值
    change(ref_a_left); // 编译不过,左值引用ref_a_left本身也是个左值
    change(ref_a_right); // 编译不过,右值引用ref_a_right本身也是个左值
     
    change(std::move(a)); // 编译通过
    change(std::move(ref_a_right)); // 编译通过
    change(std::move(ref_a_left)); // 编译通过
 
    change(5); // 当然可以直接接右值,编译通过
     
    cout << &a << ' ';
    cout << &ref_a_left << ' ';
    cout << &ref_a_right;
    // 打印这三个左值的地址,都是一样的
}

看完后你可能有个问题,std::move会返回一个右值引用int &&,它是左值还是右值呢?

或者说:作为函数返回值的 && 是右值(函数返回对象在右边),直接声明出来的 && 是左值。

** 这同样也符合第一章对左值,右值的判定方式:其实引用和普通变量是一样的,int &&ref = std::move(a)和 int a = 5没有什么区别,等号左边就是左值,右边就是右值。**

最后,从上述分析中我们得到如下结论:

从性能上讲,左右值引用没有区别,传参使用左右值引用都可以避免拷贝。

右值引用可以直接指向右值,也可以通过std::move指向左值;

而左值引用只能指向左值(const左值引用也能指向右值)

作为函数形参时,右值引用更灵活。

虽然const左值引用也可以做到左右值都接受,但它无法修改,有一定局限性。

void f(const int& n) {
    n += 1; // 编译失败,const左值引用不能修改指向变量
}

void f2(int && n) {
    n += 1; // ok
}

int main() {
    f(5);
    f2(5);
}

标签:std,右值,int,左值,引用,ref
From: https://www.cnblogs.com/niumachen/p/18429260

相关文章

  • 右值引用、转移和完美转发(刨析std::move的实现原理)
    文章目录0、类型和值类别1、左值2、右值2.1纯右值2.2将亡值3、左值引用和右值引用左值引用左值引用的特性常量左值引用的特性右值引用4、&&的特性4.1函数重载5、转移和完美转发5.1std::move5.2剖析move的实现std::remove_reference::type5.3forward0......
  • C++ 左值和右值
    一般而言,一个左值表达式表示的是一个对象的身份,而一个右值表达式表示的是对象的值。我们不能将其绑定到要求转换的表达式、字面常量或是返回右值的表达式(参见2.3.1节,第46页)。右值引用有着完全相反的绑定特性:我们可以将一个右值引用绑定到这类表达式上,但不能将一个右值引用......
  • C++ 中的左值引用和右值引用
    1、前言概念左值引用一直有这个概念。C++11中才出现了右值引用的概念。注意本文只讨论左值引用和右值引用,但需要提前了解一下左值和右值。//以下的a、p、*p、b都是左值inta=3;int*p=&a;*p;constintb=2;doublex=1.3,y=3.8;......
  • 《深入理解 C++中的右值引用:开启高效编程新篇章》
    在C++的编程世界中,右值引用是一个强大而又富有特色的特性,它为程序员提供了更高效的资源管理方式和更灵活的编程手段。本文将带你深入探讨C++中的右值引用,揭示其独特的特点和强大的功能。一、标题背后的意义C++中的右值引用究竟有何特殊之处?为何它成为了C++编程中的热点......
  • 【C++】看完就会--右值引用!!!
    右值引用一、什么是右值?什么是左值?二、右值引用三、右值引用的好处四、万能引用五、完美转发一、什么是右值?什么是左值?首先,当我们看到右值的时候,我们很自然的就会产生疑问?什么的右边呢?等号的右边吗?那么如果是按赋值=符号的右边来定义的话,那么,左值是不是就是=符号......
  • 【重学c++primer】第五章第二节 深入浅出:左值和右值
    文章目录左值右值传统的左值和右值划分glvalueprvaluexvalue总结左值和右值的转换左值转右值decltype左值右值传统的左值和右值划分左值:英文为leftvalue,简写lvalue右值:英文为rightvalue,简写rvalue一个左一个右,这个左右的判定是针对什么呢?实际上是针对等......
  • 第18 章探讨 C++新标准 移动语义和右值引用
    第18章探讨C++新标准移动语义和右值引用第18章探讨C++新标准移动语义和右值引用文章目录第18章探讨C++新标准移动语义和右值引用18.2移动语义和右值引用程序清单18.2useless.cpp18.2移动语义和右值引用现在介绍本书前面未讨论的主题。C++11支持移动语......
  • 左值有地址,为社么还要std::move()?
    我把左值传入函数,左值有地址不是可以直接进行移动吗,为什么还要转为右值?原因:一般函数都有设置左值引用的接口和右值引用的接口,右值就是为了传入参数后销毁原参数,左值引用就是为了保护原参数而进行深拷贝。所以一般想实现移动语义就用右值引用的接口。在C++中,移动语义的核心思......
  • C++ - 左值和右值的区别
    示例:来看一行简单的代码1inta=10;这行代码,"="左边就是左值,"="右边的则为右值,那他们到底有什么不同呢?如果是Java、PHP等后端同学,会称以左边的"a"为变量,右边的"10"为字面量,而到了C++这里,我们就需要对他理解更多一点。这行代码运行起来,是在系统内存中申......
  • 【C++11】C++11新纪元:深入探索右值引用与移动语义
    ......