如何理解C++ 临时变量的常量性
1.认识临时变量的常量性
关于临时变量的常量性,先看一段代码。
void print(string& str) { cout<<str<<endl; } //如此调用会报编译错误 print("hello world");
在Linux环境使用g++编译,会出现: invalid initialization of non-const reference of type ‘std::string&' from a temporary of type 'std::string'的错误。其中文意思为临时变量无法为非const引用初始化。出错的原因是编译器根据字符串"hello world"构造一个string类型的临时对象,这个临时变量具有const属性,当这个临时变量传递给非const的string&引用类型时,无法隐式完成const到非const的类型转换,便出现上面的编译错误。解决办法是将print()函数的参数改为常引用。代码修改如下,可顺利通过编译。
void print(const string& str) { cout<<str<<endl; } //顺利通过编译 print("hello world");
通过以上代码,可以看出在设计函数时,形参尽可能地使用const,这样可以使代码更为健壮,将错误暴露于编译阶段。
2.临时变量常量性的原因
为什么临时对象作为引用参数传递时,形参必须是常量引用呢?很多人对此的解释是临时变量是常量,不允许赋值改动,所以作为非常量引用传递时,编译器就会报错。这个解释在理解临时变量不能作为非const引用参数这个问题上是可以的,但不够准确。事实上,临时变量是可以作为左值(Lvalue) 并被赋值的,请看下面的代码:
class IntClass { private: int x; public: IntClass(int value):x(value){} friend ostream& operator<<(ostream &os, const IntClass &intc); }; //重载operator<< ostream& operator<<(ostream &os, const IntClass &intc) { os<<intc.x; return os; } int main(int argc,char* argv[]) { cout << (IntClass(6) = IntClass(8))<<endl; }
程序输出:
8
以上代码正确编译运行,没有错误。IntClass(6)表示生成一个无名临时变量并作为左值被修改,所以临时变量并不是常量,只是编译器从语义层面限制了临时变量传递给非const引用。注意,这里与《C++编程思想》在第八章中的“临时量”小节中认为“编译器使所有的临时量自动设为const”的说法有些不同。
那编译器为何作出如此限制呢?如果一个实参以非const引用传入函数,编译器有理由认为该实参会在函数中被修改,并且这个被修改的引用在函数返回后要发挥作用。但如果把一个临时变量当作非const引用参数传进来,由于临时变量的特殊性,临时变量所在的表达式执行结束后,临时变量就会被释放,所以,一般说来, 修改一个临时变量是毫无意义的,据此,C++编译器加入了临时变量不能作为非const引用实参这个语义限制,意在限制这个非常规用法的潜在错误。
以上就是如何理解C++ 临时变量的常量性的详细内容,更多关于C++ 临时变量的常量性的资料请关注我们其它相关文章!
相关推荐
-
详解C++中的常量
常量是固定值,在程序执行期间不会改变.这些固定的值,又叫做字面量. 常量可以是任何的基本数据类型,可分为整型数字.浮点数字.字符.字符串和布尔值. 常量就像是常规的变量,只不过常量的值在定义后不能进行修改. 整数常量 整数常量可以是十进制.八进制或十六进制的常量.前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制. 整数常量也可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long).后缀可以是大写,也可以是小
-
C++整数常量的前缀和后缀的示例代码
这篇文章给大家介绍了C++整数常量的前缀和后缀的示例代码,详情如下所示: 在C/C++中,整数常量可以加上不同的前缀,表示不同的进制: 十进制:不带前缀,默认表示为十进制 八进制:0 表示八进制 十六进制:0x 或 0X 表示十六进制 整数常量还可以加上不同的后缀,表示不同的数据类型: 无符号:U 长整数:L 示例代码如下: #include <iostream> using namespace std; int main() { int x = 666; // 十进制 int y = 020
-
c++常量详解
概念 常量是存放固定且不可变值的,一旦确定初始值则在程序其它地方不可改变, 所以const对象必须初始化.常量一般使用const关键字来修饰. const 对象可以大致分为三类: 1. const int a const int a =10; int const b =10; 这两种格式是完全相同的.也就是说const 与int哪个写前都不影响语义.有了这个概念后,我们来看这两个家伙:const int * pi与int const * pi ,它们的语义有不同吗? 你只要记住一点,int 与c
-
C++常量详解一(常量指针与常量引用的初始化)
1.常量 1.1.常量的初始化: const对象一旦创建后其值就不能再改变,所以const对象必须初始化.这里我们要注意一点,像const int *p和const int &r都并不是const对象.因为const int *p只是表示不能通过p改变p所指的对象的值,p的值是可以变的,所以p可以不用初始化.至于r ,引用本身就不是对象,所以r也并不是const对象,r之所以一定初始化,是因为引用必须初始化.对于以上内容,你也可以理解为底层const 修饰的并不是const对象,还要注意像con
-
详解C++中常量的类型与定义
常量是固定值,在程序执行期间不会改变.这些固定的值,又叫做字面量. 常量可以是任何的基本数据类型,可分为整型数字.浮点数字.字符.字符串和布尔值. 常量就像是常规的变量,只不过常量的值在定义后不能进行修改. 整数常量 整数常量可以是十进制.八进制或十六进制的常量.前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制. 整数常量也可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long).后缀可以是大写,也可以是小
-
C++ const引用、临时变量 引用参数详解
C++引用-临时变量.引用参数和const引用 如果实参与引用参数不匹配,C++将生成临时变量.如果引用参数是const,则编译器在下面两种情况下生成临时变量: 实参类型是正确的,但不是左值 实参类型不正确,但可以转换为正确的类型 左值参数是可被引用的数据对象,例如,变量.数组元素.结构成员.引用和被解除引用的指针都是左值,非左值包括字面常量和包含多项式的表达式.定义一个函数 Double refcube(const double& ra) { Returnra*ra*ra; } double
-
C++ 常量成员常量返回值详解
总结: 1.常量数据成员,形式:const Type m_tData; 1)常量数据成员,需要在构造函数列表中给出,构造函数中可以用常量赋值,也可以实例化的时候赋值. 2)赋值函数中不能赋值,起到保护常量数据成员的作用,和友元作用相反. 2.常量成员函数,形式:type funname(type1 arg1,type2 arg2,...) const 1)常量成员函数,不能修改类数据成员,不能调用非常量函数. 2)常量成员函数的作用,可以有效的将类的函数分为可以修改类的函数,和不能修改类的函数:
-
c++中临时变量不能作为非const的引用参数的方法
试看下面的代码: #include <iostream> using namespace std; void f(int &a) { cout << "f(" << a << ") is being called" << endl; } void g(const int &a) { cout << "g(" << a << "
-
简单总结C++中指针常量与常量指针的区别
我们先回顾下,什么是指针?什么是常量?指针是一种特殊的变量,它里面存储的内容是内存地址.常量是指其里面存储的内容不能发生改变的量.明白了这两个概念后,我们现在正式进入指针常量与常量指针. 1.指针常量与常量指针的概念 指针常量就是指针本身是常量,换句话说,就是指针里面所存储的内容(内存地址)是常量,不能改变.但是,内存地址所对应的内容是可以通过指针改变的. 常量指针就是指向常量的指针,换句话说,就是指针指向的是常量,它指向的内容不能发生改变,不能通过指针来修改它指向的内容.但是,指针自身不是常量
-
如何理解C++ 临时变量的常量性
1.认识临时变量的常量性 关于临时变量的常量性,先看一段代码. void print(string& str) { cout<<str<<endl; } //如此调用会报编译错误 print("hello world"); 在Linux环境使用g++编译,会出现: invalid initialization of non-const reference of type 'std::string&' from a temporary of typ
-
深入理解Python变量与常量
变量是计算机内存中的一块区域,变量可以存储规定范围内的值,而且值可以改变.基于变量的数据类型,解释器会分配指定内存,并决定什么数据可以被存储在内存中.常量是一块只读的内存区域,常量一旦被初始化就不能被改变. 变量命名字母.数字.下划线组成,不能以数字开头,前文有说不在赘述. 变量赋值 Python中的变量不需要声明,变量的赋值操作即是变量的声明和定义的过程.每个变量在内存中创建都包括变量的标识.名称.和数据这些信息. Python中一次新的赋值,将创建一个新的变量.即使变量的名称相同,变量的标识
-
深入理解Swift中的变量与常量
前言 最近在学习Swift这门新语言,对于熟练掌握OC编程的iOS开发者来说其实很容易上手,但Swift的确在语法和编程习惯上改变了很多,对于从未了解OC语言而从Swift开始学习iOS开发的新手来说可能上手有一定难度,下面我将这段时间的学习成果结合在网上搜索的知识做一个简单的汇总,希望可以帮助到正在学习Swift的小伙伴们. 变量和常量的定义 Swift开发文档中是这样定义变量和常量的:常量和变量把名字和一个特定类型的值关联起来.常量的值一旦设置好便不能再被更改,然而变量可以在将来被设置为不同
-
django template实现定义临时变量,自定义赋值、自增实例
定义临时变量: {% with i=1 %} {{i}} {% endwith %} 定义对临时变量操作的tag 在templatetags中创建set_val.py 内容是 from django import template import logging register = template.Library() class SetVarNode(template.Node): def __init__(self, var_name, var_value): self.var_name =
-
Python中的变量与常量
目录 一.变量.常量的区别 二.变量 1. Python中的变量不需要声明类型 2. 用"="号来给变量赋值 3. 赋值 4. 变量 5. "=" 6. Python允许同时为多个变量赋值 三.常量 四.总结 一.变量.常量的区别 变量:在程序运行过程中,值会发生变化的量. 常量:在程序运行过程中,值不会发生变化的量. 无论是变量还是常量,在创建时都会在内存中开辟一块空间,用于保存它的值. 二.变量 1. Python中的变量不需要声明类型 这是根据Python的动
-
PHP中应该避免使用同名变量(拆分临时变量)
当一个临时变量被赋值多次时,那么将其拆分成多个,除非它是一个循环计数器. Motivation 临时变量有这多种不同的用途.比如它们可被用作循环中的计数器,在循环中保存结果集,亦或保存一个冗长的表达式的计算结果等等. 这些类型的变量(容器)应该只赋值一次.如果一个同名的临时变量被赋予多个职责,将会影响代码的可读性.这个时候我们应当引入一个新的临时变量以使代码更加清晰易懂. 可能有些注重性能的人会说,引入一个新的变量将会占用更多的内存.的确如此,但是注册一个新的变量不会吸干服务器内存的,这一点请放
-
java中变量和常量详解
变量和常量 在程序中存在大量的数据来代表程序的状态,其中有些数据在程序的运行过程中值会发生改变,有些数据在程序运行过程中值不能发生改变,这些数据在程序中分别被叫做变量和常量. 在实际的程序中,可以根据数据在程序运行中是否发生改变,来选择应该是使用变量代表还是常量代表. 变量 变量代表程序的状态.程序通过改变变量的值来改变整个程序的状态,或者说得更大一些,也就是实现程序的功能逻辑. 为了方便的引用变量的值,在程序中需要为变量设定一个名称,这就是变量名.例如在2D游戏程序中,需要代表人物的位置,则需
-
对Python 获取类的成员变量及临时变量的方法详解
利用Python反射机制,从代码块中静态获取参数: co_argcount: 普通参数的总数,不包括参数和*参数. co_names: 所有的参数名(包括参数和*参数)和局部变量名的元组. co_varnames: 所有的局部变量名的元组. co_filename: 源代码所在的文件名. co_flags: 这是一个数值,每一个二进制位都包含了特定信息.较关注的是0b100(0x4)和0b1000(0x8),如果co_flags & 0b100 != 0,说明使用了*args参数:如果co_fl
随机推荐
- 浅析Ajax语法
- SQL Server 在Management Studio中使用Web浏览器
- oracle dba 应该熟悉的命令
- 在vue.js中抽出公共代码的方法示例
- Windows Server 2003 R2 Beta 2将公测
- asp.net 购物车实现详细代码
- jQuery实现为控件添加水印文字效果(附源码)
- JS实现下拉菜单赋值到文本框的方法
- ASP.NET MVC 中实现基于角色的权限控制的处理方法
- 在ASP中连接MySQL数据库的方法,最好的通过ODBC方法
- c语言实现24小时制转换为12小时制示例
- MySQL中批量删除指定前缀表的sql语句
- PowerShell创建Byte数组例子
- 详解Python3.1版本带来的核心变化
- htm调用JS代码
- js密码强度检验
- C++使用递归方法求n阶勒让德多项式完整实例
- Java判断是否为闰年的方法示例
- Android抽象布局——include、merge 、ViewStub详解
- Cat 6509 NAT 实例