C++标准:C++不允许修改任何基本型别(包括指针)的暂时值

从《C++标准库》一书中看到这样一句话:C++不允许修改任何基本型别(包括指针)的暂时值,想了半天,实在不理解。基本类型char,int,float等等还有暂时值?例如int a=2,那么这个a的暂时值是哪个呢?我能不能把2理解为a的暂时值?如果2为暂时值,显然不行,因为你根本无法修改2,那么那句话就毫无意义了。暂时值先不管了,不知道怎么找,搜了很多,明白一个大概意思,先看几个从网上找到的例子:

#include<iostream>
using namespace std;
void main()
{
    int a = 4;
    a++ = 5;

    int *b;
    *b = 4;
    *b++ = 5;
}

a++;
后缀++ 返回的是一个(临时的)右值,其值是a的原值, 不能被赋值。(注意,这里说的是右值)
*b++ = 5;
该表达式是 *(b++) = 5;
也就是先对指针加1, 再解引用。
b++ 同a++一样, 是一个临时的右值,(其值是b的原值), 不能被赋值, 比如下面的代码不合法:
b++ = ptr;
b++表达式产生的是一个临时的指针值, 对指针解引用(当然,该值必须指向合法位置)之后, 就是一个左值了,所以:
*b++ = 5; 就是合法的。

再看一个例子;

#include <iostream>
using namespace std;
class my
{

public:
    my(int j=0):i(j){}
    int i;
    void operator=(my&out)//这里重定义一个赋值操作符=,为下面的赋值做准备。
    {
        i=out.i;
    }
};
my fun()
{
    my temp(1);
    return temp;//这里返回一个类的临时变量
}
int fun2()
{
    int a;
    return a;//这里返回一个普通int临时变量

}
int main()
{
    my out(2);
    fun()=out;   //这里可以对类的临时变量赋值
    fun2()=3;   //但是这里对普通int类型的变量就会出错
}

fun2()返回的是一个右值,不能赋值,只能这么解释了。

再看《C++标准库》提到的问题:

vector<int> coll;
.....
sort(++coll.begin(),coll.end());

书上说会编译失败。我在VS2012下面编译却没有问题。

记住一点:右值不能被修改。

时间: 2024-11-01 00:32:53

C++标准:C++不允许修改任何基本型别(包括指针)的暂时值的相关文章

标C编程笔记day07 常用标准库介绍、字符串输入处理、字符指针的使用

常用标准库: assert.h:断言,包含assert宏.可以进行自我检查 ctype.h:字符处理,字符的分类,大小转换 errno.h:错误信息处理 float.h:浮点数特性 limits.h:整数的大小,提供了描述整数类型的宏 lcale.h:本地化 math.h:数学函数 setjmp.h:跳转 signal.h:信号处理 stdarg.h:可变长参数处理 stddef.h:经常使用的类型的定义 stdio.h:输入输出 string.h:字符串处理 stdlib.h:其他函数,字符串

linux 文件目录标准,变量,修改字符集运行级别,设置别名和软件安装,(nginx),换源

# FHS 在早期的 UNIX 系统中,各个厂家各自定义了自己的 UNIX 系统文件目录,比较混乱.Linux 面世不久后,对文件目录进行了标准化,于1994年对根文件目录做了统一的规范,推出 FHS ( Filesystem Hierarchy Standard ) 的 Linux 文件系统层次结构标准.FHS 标准规定了 Linux 根目录各文件夹的名称及作用,统一了Linux界命名混乱的局面. `FHS` 是根据以往无数 Linux 用户和开发者的经验总结出来的,并且会维持更新! 无论何种

标准屏幕字段描述修改

实现步骤: 1.修改屏幕字段对应的DATA ELEMENT的描述,这里会涉及到中英的翻译容易忽略需注意一下. 2.找到该屏幕,点击激活按钮,此时会提示禁止修改或者弹出让输入Object key的界面,但不用在纠结于这个,一般没什么影响.    (找该屏幕,你可以进入主程序,根据Status里面的该屏幕序号在主程序框架中找到该屏幕,激活) 3.重新执行事务代码试试,查看查看该屏幕,修改结果实现. 原文地址:https://www.cnblogs.com/libo2019/p/10428505.ht

SQL SERVER 修改数据库名称(包括 db.mdf 名称的修改)

折腾SQL SERVER 2012,弄了一个上午修改数据库名,主要是需要修改db.mdf 和db_log.ldf的名字,总算解决了.在这里记下,以后再要修改了就别忘了. 假设原来数据库名为db,附加数据库为db.mdf和db_log.ldf. 需要改成dbt,及dbt.mdf和dbt_log.ldf. 步骤: 1.首先把原来的数据库进行备份(选择数据库->右键->任务->备份),备份出db.bak文件. 2.右键->任务->还原->数据库,跳出“还原数据库”窗口. 3.

Oracle的列操作(增加列,修改列,删除列),包括操作多列

增加一列: alter table emp4 add test varchar2(10); 修改一列: alter table emp4 modify test varchar2(20); 删除一列: alter table emp4 drop column test; 这里要注意几个地方,首先,增加和修改列是不需要加关键字COLUMN,否则会报错ora-00905. 其次,对删除单列的话,一定要加COLUMN,然后记住,删除是不需要加列类型的. 增加多列: alter table emp4 a

c#(winform,webform通用)利用npoi将xls文件复制为xlsx文件(excel的修改,保存,包括excel2003-office2007+的处理)

1.程序界面 每次需要处理excel文件的时候,都是去百度找方案,真是气一头火,今天好好总结一下,下次就不用度娘了. 我是用winform来试验的,因为winform比较方便测试,实际上只要是在.net平台上,c#写的程序,都是通用的. 2.所需dll下载地址 npoi.zip  这里包含了所有所需要的dll文件,引入到项目中就可以了 3.代码 public void writeExcel(string readExcelPath, string writeExcelPath) { //需要读取

成员函数的const不能被修改,包括指针

#include <iostream> class A { private: std::string a; public: A(std::string b) :a(b){} char& operator[](int b)const { return a[b]; } }; int main() { A a("hello"); //a[0]='j'; 不能 char*p = &a[0]; *p = 'j'; 也不能,编译器信息:“return”: 无法从“con

iOS 根据UIImage 修改UIImageView Frame (包括截取图片中间部分)

iOS UIImageView 根据需求调整frame 1.图片的宽和高不相等,截取图片的中间部分,截取的部分Size明确 2.图片的宽度要等于其父视图的类的宽度,然后根据宽度计算高度,保证 图片不变形,显示正常 3.图片的宽度或高度大于其父视图的类的宽的或高度,如果是宽度的问题, 就以其父视图的宽度为准,确定图片的显示宽度:如果是高度的问题,就以 其父视图的高度为准,确定图片的显示高度. 以上三种情况,具体示例依次如下: 第一种情况,调用方法: - (void)imageLoadedFinis

STL学习笔记(迭代器相关辅助函数)

advance()可令迭代器前进 #include <iterator> void advance(InputIterator& pos,Dist n); 面对Random Access(随机存取)迭代器,该函数只是简单的调用pos+=n.而对于其他任何类型的迭代器则调用++pos(--pos)n次. distance()可以处理迭代器之间的距离 #include <iterator> Dist distance(InputIterator pos1,InputIterat