C++中让人忽视的左值和右值
前言
为了了解C++11的新特性右值引用,不得不重新认识一下左右值。学习之初,最快的理解,莫过于望文生义了,右值那就是赋值号右边的值,左值就是赋值号左边的值。在中学的数学的学习中,我们理解的是,左值等价于等号左边的值,右值等价于等号右边的值;当我们继续学习C语言时,等号=不再叫等号,盖头换面叫做赋值号;那么来到C++我们还能这么理解吗?答案是部分否定的。
假如你现在还是这样理解,那么请继续往下......
C++中何为左值lvalue和右值rvalue?
左值lvalue:可被引用的数据对象,例如,变量、数组元素、结构成员、引用和解除引用的指针都是左值。在C语言中,左值最初指的是出现在赋值语句左边的实体,但这是引入const之前的情况。now,常规变量和const变量都可视为左值,因为可通过地址访问它们。常规变量属于可修改的左值,const变量属于不可修改的左值。左值基本上和以前的认知没有太大的改变。
右值rvalue:字面常量(用括号括起来的字符串除外,因为它们表示地址)、包含多项的表达式以及返回值的函数(条件是该函数返回的不是引用)。
简单的区别左值和右值:
右值就是一个临时变量(后面将详细的解释),只有临时地址空间,左值有其地址空间,换句话说,使用取地址符&对某个值取地址,如果不能得到地址,则是右值!
例如:
int a = 0;
cout << &a << endl; // ok! lvalue
cout << &404; // error! rvalue
对于前面提到的右值的特性:
1) 允许调用成员函数。
2) 只能被 const reference 指向。
3) 右值不能当成左值使用,但左值可以当成右值使用
临时变量
仅当函数参数为const reference时,临时变量才能与之匹配。
什么时候将创建临时变量呢?
如果引用参数是const,则编译器将在下面两种情况下生成临时变量:
1. 实参的类型正确,但不是左值
2. 实参的类型不正确,但可以转换为正确的类型
Example:
double cube(const double &ra)
{
return ra * ra * ra;
} double side = 3.0;
double* pd = &side;
double& rd = side;
long edge = 5L;
double lens[] = {2.0, 5.0, 10.0, 12.0}; double c1 = cube(side);
double c2 = cube(lens[]);
double c3 = cube(rd);
double c4 = cube(*pd); double c5 = cube(edge); // ra是临时变量
double c6 = cube(7.0); // ra是临时变量
double c7 = cube(side + 4.0); // ra是临时变量
参数side、lens[2]、rd和*pd都是有名称的、double类型的数据对象,因此不需要借助临时变量,可以为其创建引用。
然而edge虽然有名称但是类型却不正确,正好符合产生临时变量的情况2 “实参的类型不正确,但可以转换为正确的类型” ,double引用不能指向long。参数7.0和side + 4.0的类型都正确,但是木有名称,属于右值。在这些情况下,编译器都会生成一个临时匿名变量,并让ra指向它。这些变量生命周期只在函数调用期间,此后编译器便会随意的删除。
为何临时变量 or 右值 对const引用的限制时合理的呢?
请看下面的例子:
void swapr(int& a, int& b) // swapr()完成数的交换的功能
{
int temp; temp = a;
a = b;
b = temp;
} long a = , b = ;
swapr(a, b);
这里我们使用反证法,假设这个调用是木有错误的,那么这里的类型不匹配,因此编译器将创建两个int临时变量,将它们初始化为3和5,然后交换临时变量的内容,但是这只是交换了两个临时变量的值,a和 b并没有交换,这与swapr()函数完成的功能是相悖的。
总结来说,如果接受引用参数的函数的意图是修改作为参数传递的变量,则创建临时变量将阻止这种意图的实现。解决方法是,禁止创建临时变量。因此这个调用也是错误的。如果函数调用的参数是右值或与相应的const引用参数的类型不匹配,则C++将创建类型正确的匿名变量,将函数调用的参数的值传递给该匿名变量,并让参数来引用该变量
C++中让人忽视的左值和右值的更多相关文章
- C++中的左值与右值(二)
以前以为自己把左值和右值已经弄清楚了,果然发现自己还是太年轻了,下面的这些东西是自己通过在网上拾人牙慧,加上自己的理解写的. 1. 2. 怎么区分左值和右值:知乎大神@顾露的回答. 3. 我们不能直接 ...
- c++中的左值与右值
左值(lvalue)和右值(rvalue)是 c/c++ 中一个比较晦涩基础的概念,不少写了很久c/c++的人甚至没有听过这个名字,但这个概念到了 c++11 后却变得十分重要,它们是理解 move/ ...
- C++中的左值和右值
左值和右值的定义 在C++中,能够放到赋值操作符=左边的是左值,能够放到赋值操作符右边的是右值.有些变量既能够当左值又能够当右值.进一步来讲,左值为Lvalue,事实上L代表Location,表示在内 ...
- C++中 左值和右值的区别
总结: C++11中所有的值属于左值,右值两者之一. 左值引用:指的是可以放在赋值表达式左边的事物——在堆上或者栈上分配的命名对象或者其他对象成员——有明确的内存地址. 对左值的const引用创建临时 ...
- c++中的左值和右值的理解
1.左值和右值的概念 C++中左值(lvalue)和右值(rvalue)是比较基础的概念,虽然平常几乎用不到,但C++11之后变得十分重要,它是理解 move/forward 等新语义的基础. 左值与 ...
- C笔记-左值与右值
目录 前言:工欲善其事,必先利其器 两种资料 参考资料及其使用说明 官方对于左值和右值的定义 实际使用时的疑问 左值的涵盖范围 重要概念: 左值转化(lvalue conversion) 左值与指针 ...
- c++左值和右值
c++编程中如果出现把一个函数的返回值.强行转化后的对象 作为函数的参数传进去时,编译器会报错的情况.这时候就该注意了,你需要把该函数的参数类型前加上const修饰. 原因在于c++的左值和右值有所区 ...
- c++ 左值 和 右值
什么是lvalue, 什么是rvalue? lvalue: 具有存储性质的对象,即lvalue对象,是指要实际占用内存空间.有内存地址的那些实体对象,例如:变量(variables).函数.函数指针等 ...
- c++ 11 移动语义、std::move 左值、右值、将亡值、纯右值、右值引用
为什么要用移动语义 先看看下面的代码 // rvalue_reference.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #includ ...
随机推荐
- [LeetCode] 210. 课程表 II
题目链接:https://leetcode-cn.com/problems/course-schedule-ii/ 题目描述: 现在你总共有 n 门课需要选,记为 0 到 n-1. 在选修某些课程之前 ...
- vue.js学习记录
vue.js学习记录 文章已同步我的github笔记https://github.com/ymblog/blog,欢迎大家加star~~ vue实例 生命周期 beforeCreate:不能访问thi ...
- PY个欧拉筛
大数据用 python? 速度感人 突然来了一发 python 欧拉筛,调了半天之后输入 1e7 过了几秒钟之后出解了,PY 果然神速 没学过 PY 的小同学可以当做 VB 的阅读程序,反正语言隔离都 ...
- C#配合大数据开发,nest.dll的使用
一,添加Nest.dll引用 结果如下多了如下DLL: Elasticsearch.Net.dll,Nest.dll 二,上代码: using Common.EsModel; using Elasti ...
- 关于BeanUtils.copyProperties的用法和优缺点
一.简介: BeanUtils提供对Java反射和自省API的包装.其主要目的是利用反射机制对JavaBean的属性进行处理.我们知道,一个JavaBean通常包含了大量的属性,很多情况下,对Jav ...
- LabWindows/CVI 下载
LabWindows/CVI 是National Instruments 公司(美国国家仪器公司,简称NI 公司)推出的交互式C 语言开发平台.LabWindows/CVI 将功能强大.使用灵活的C ...
- mkdir -建立目录
总览 mkdir [选项] 目录... POSIX 选项: [-p] [-m mode] GNU 选项(缩写): [-p] [-m mode] [--verbose] [--help] [--vers ...
- mirror - 映射在远端节点上的档案
总览 SYNOPSIS mirror [flags] -gsite:pathname mirror [flags] [package-files] 描述 DESCRIPTION Mirror 是以 P ...
- muduo
https://blog.csdn.net/zxm342698145/article/details/80689016 https://blog.csdn.net/u010087886/article ...
- case_match
//箭头符号 => 隔开了模式和表达式.//选择器 match {备选项}.//只要发现有一个匹配的case,剩下的case不会继续匹配. //object case_test {//// de ...