C++左值和右值学习笔记

 更新时间:2023年10月31日 09:13:06   作者:Totn  
这篇文章主要为大家介绍了C++左值和右值学习笔记的重点讲解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

来看一行简单的代码

int a = 10;

这行代码,"=" 左边就是左值,"="右边的则为右值,那他们到底有什么不同呢?

如果是Java、PHP等后端同学,会称以左边的"a"为变量,右边的"10"为字面量,而到了C++这里,我们就需要对他理解更多一点。

这行代码运行起来,是在系统内存中申请了一块空间,命名为"a",然后把"10"这个值装入了这个单内存空间中,内存中的空间是有地址的,并且和"a"这个名字绑在一起,当我们提到"a",就能知道他所代表的内存地址,这也是所谓的"可寻址"。

在C++中,每个表达式都具有一个值和一个类型。左值和右值描述了表达式的可寻址性和持久性。

首先,让我们来看一下左值的概念。左值是指可以被取地址的表达式,或者说具有标识符的表达式。左值表示一个内存位置,它具有持久性,可以在程序的不同部分访问和修改。简而言之,左值可以出现在赋值运算符的左边。

左值的特点

int x = 10;     // 'x' 是一个左值,可以被赋值
int* p = &x;    // '&x' 是一个左值,可以取其地址
int arr[5];     // 'arr' 是一个左值,可以被访问和修改

接下来,我们来看一下右值的概念。右值是指不可被取地址的表达式,或者说临时生成的表达式。右值表示一个临时的值,它通常只能用于赋值或传递给函数,没有持久性。简而言之,右值可以出现在赋值运算符的右边。

右值的特点

int a = 5;              // '5' 是一个右值
int b = a + 3;          // 'a + 3' 是一个右值
int* ptr = new int(10); // 'new int(10)' 返回一个右值

需要注意的是,C++11引入了右值引用的概念,即可以对右值进行引用的类型。右值引用允许我们更有效地管理资源,如移动语义和完美转发。

综上所述,左值表示持久的可寻址表达式,而右值表示临时的不可寻址表达式。理解左值和右值的概念对于理解C++中的赋值、函数调用和参数传递等操作是非常重要的。

函数返回值

那么,一个函数返回值,应该是左值还是右值?

当一个函数被调用时,它会在栈上创建一个新的帧来存储该函数的局部变量、参数以及其他信息。该帧在函数返回时销毁。

因为函数返回值通常是通过寄存器或者特殊寄存器(如eax)返回的,它们的地址在栈帧被销毁后就不能再访问了。所以不能直接对函数返回值取址。

但是,如果你需要返回一个指向已经存在的内存块的指针,然后在函数外使用该指针访问内存块,那么是可以的。例如:

int* foo() {
    int x = 10;
    return &x;
}

int main() {
    int* p = foo();
    std::cout << *p; // undefined behavior
    return 0;
}

上述代码中的foo()函数返回了一个指向局部变量x的指针。

这会导致undefined behavior,因为x在函数返回时就被销毁了,所以p指向的内存块中可能包含任意的值。

所以,不能直接对函数返回值取址,函数返回值是一个右值。

但如何函数返回的是指向已经存在的内存块的指针,即不是函数内定义的东西,那么取址是没有问题的。

以上就是C++左值和右值学习笔记的详细内容,更多关于C++左值 右值的资料请关注脚本之家其它相关文章!

相关文章

  • C++ 虚函数表图文解析

    C++ 虚函数表图文解析

    最近学了设计模式中的简单工厂模式,对多态有了具体的认识。于是补了补多态、虚函数、虚函数表相关的知识,本文介绍了C++ 虚函数表,感兴趣的了解一下
    2021-05-05
  • 谈谈C++学习之Pair的使用方法

    谈谈C++学习之Pair的使用方法

    pair是一种模板类型,其中包含两个数据值,两个数据的类型可以不同,本篇详细的介绍了Pair的使用方法和实例,有兴趣的同学可以了解一下。
    2016-12-12
  • C++ 标准库 <chrono>的具体使用

    C++ 标准库 <chrono>的具体使用

    chrono>引入于 C++11,提供了类型安全的时间度量体系,本文就来详细的介绍一下<chrono>的使用,感兴趣的可以了解一下
    2026-02-02
  • C++11新特性全解析新的类功能、lambda、包装器详解

    C++11新特性全解析新的类功能、lambda、包装器详解

    本文主要介绍了C++11中新增的移动语义、默认函数、删除函数、override和final关键字,以及STL中的新容器和接口、lambda表达式、function和bind函数模板,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2026-02-02
  • C++中的std::funture和std::promise实例详解

    C++中的std::funture和std::promise实例详解

    在线程池中获取线程执行函数的返回值时,通常使用 std::future 而不是 std::promise 来传递返回值,这篇文章主要介绍了C++中的std::funture和std::promise实例详解,需要的朋友可以参考下
    2024-05-05
  • 教你分辨C++堆与栈的区别

    教你分辨C++堆与栈的区别

    堆与栈的区别有:1、栈由系统自动分配,而堆是人为申请开辟;2、栈获得的空间较小,而堆获得的空间较大;3、栈由系统自动分配,速度较快,而堆一般速度比较慢;4、栈是连续的空间,而堆是不连续的空间
    2021-06-06
  • C++中overload,override,overwrite的区别详细解析

    C++中overload,override,overwrite的区别详细解析

    以下是对C++中overload,override,overwrite的区别进行了详细的分析介绍,需要的朋友可以过来参考下
    2013-09-09
  • 浅谈const变量赋值报错分析

    浅谈const变量赋值报错分析

    在类中 只有静态变量能赋值 如果你不赋值 编译器会认为你这个变量根本没用 不能被修改 又没有初始值 两个办法 在构造函数的初始化列表赋值 或者在const前面加一个static
    2015-07-07
  • VScode上配置 c语言环境的图文教程

    VScode上配置 c语言环境的图文教程

    这篇文章主要介绍了配置VScode c语言环境,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • C++编译期字符串处理方法

    C++编译期字符串处理方法

    这篇文章给大家介绍了C++编译期字符串处理方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2026-03-03

最新评论