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 << ") is being called" << endl;
}

 int main()

 {
 int a = 3, b = 4;
 f(a + b); //编译错误,把临时变量作为非const的引用参数传递了
 g(a + b); //OK,把临时变量作为const&传递是允许的
}

上面的两个调用之前,a+b的值会存在一个临时变量中,当把这个临时变量传给f时,由于f的声明中,参数是int&,不是常量引用,所以产生以下编译错误:

const_ref.cpp: In function `int main()':
const_ref.cpp:14: error: invalid initialization of non-const reference of type '
  int&' from a temporary of type 'int'
const_ref.cpp:4: error: in passing argument 1 of `void f(int&)' 而在g(a+b)中,由于g定义的参数是const int&,编译通过。  问题是为什么临时变量作为引用参数传递时,必须是常量引用呢?很多人对此的解释是临时变量是常量,不允许赋值,改动,所以当作为非常量引用传递时,编译器就会报错。这个解释在关于理解临时变量不能作为非const引用参数这个问题上是可以的,但不够准确。事实上,临时变量是可以被作为左值(LValue)并被赋值的,请看下面的代码:
#include  <iostream>
using namespace std;

class CComplex {
friend CComplex operator+(const CComplex &cp1, const CComplex &cp2);
friend ostream& operator<<(ostream &os, const CComplex &cp);
private:
 int x;
public:
 CComplex(){}

 CComplex(int x1) {
 x = x1;
 }
};

CComplex operator+(const CComplex &cp1, const CComplex &cp2)

{
 CComplex cp3;
 cp3.x = cp1.x + cp2.x;
 return cp3;
} ostream& operator<<(ostream &os, const CComplex &cp)

{
 os << cp.x;
 return os;
}

int main()

{
 CComplex a(2), b(3), c(4);
 cout << (a + b) << endl;
 cout << ((a + b) = c) << endl;  //临时对象作为左值
 return 0;
}

上面的程序编译通过,而且运行结果是:

5
4

临时变量确实被赋值,而且成功了。

所以,临时变量不能作为非const引用参数,不是因为他是常量,而是因为c++编译器的一个关于语义的限制。如果一个参数是以非const引用传入,c++编译器就有理由认为程序员会在函数中修改这个值,并且这个被修改的引用在函数返回后要发挥作用。但如果你把一个临时变量当作非const引用参数传进来,由于临时变量的特殊性,程序员并不能操作临时变量,而且临时变量随时可能被释放掉,所以,一般说来,修改一个临时变量是毫无意义的,据此,c++编译器加入了临时变量不能作为非const引用的这个语义限制,意在限制这个非常规用法的潜在错误。

还不明白?OK,我们说直白一点,如果你把临时变量作为非const引用参数传递,一方面,在函数申明中,使用非常量型的引用告诉编译器你需要得到函数对某个对象的修改结果,可是你自己又不给变量起名字,直接丢弃了函数的修改结果,编译器只能说:“大哥,你这是干啥呢,告诉我把结果给你,等我把结果给你了,你又直接给扔了,你这不是在玩我呢吗?”所以编译器一怒之下就不让过了。这下大家明白了吧?

以上这篇c++中临时变量不能作为非const的引用参数的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • C++ const引用、临时变量 引用参数详解

    C++引用-临时变量.引用参数和const引用 如果实参与引用参数不匹配,C++将生成临时变量.如果引用参数是const,则编译器在下面两种情况下生成临时变量: 实参类型是正确的,但不是左值 实参类型不正确,但可以转换为正确的类型 左值参数是可被引用的数据对象,例如,变量.数组元素.结构成员.引用和被解除引用的指针都是左值,非左值包括字面常量和包含多项式的表达式.定义一个函数 Double refcube(const double& ra) { Returnra*ra*ra; } double

  • C语言中const和C++中的const 区别详解

    C语言中const和C++中的const 区别详解 C++的const和C语言的#define都可以用来定义常量,二者是有区别的,const是有数据类型的常量,而宏常量没有,编译器可以对前者进行静态类型安全检查,对后者仅是字符替换,没有类型安全检查. 而C语言中的const与C++也有很大的不同,在C语言中用const修饰的变量仍是一个变量,表示这个变量是只读的,不可显示地更改,而在C++中用const修饰过后,就变成常量了.例如下面的代码: const int n=10; int a[n];

  • C++中的const的使用详解

     C++中的const的使用详解 const在c/c++中还是会经常出现的,并且如果不理解const会在编程出现的错误而不知所措,无法理解.下面从几个角度简要理解const的内容,应该还是蛮有用的. const与指针类型 const int*p = NULL; 和int const*p = NULL;是等价的.因为const都在" * "的前面,其实是以*为标志的. 1. int x = 3; const int *p = &x; // p = &y;正确 , //*p

  • C++中const应放在类型前还是后

    我把它放在前面,但那仅仅是个人爱好问题."const T"和"T const"总是都被允许的,而且是等效的.例如: const int a = 1; // ok int const b = 2; // also ok 我猜想第一种版本可能会让少数(更加固守语法规范)的程序员感到迷惑. 为什么?当我发明"const"(最初的名称叫做"readonly",并且有一个对应的"writeonly")的时候,我就允许

  • C++ 中 const和static readonly区别

    C++ 中 const和static readonly区别 我们都知道,const和static readonly的确很像:通过类名而不是对象名进行访问,在程序中只读等等. 在多数情况下可以混用. 二者本质的区别在于,const的值是在编译期间确定的,因此只能在声明时通过常量表达式指定其值.而static readonly是在运行时计算出其值的,所以还可以通过静态构造函数来赋值. 明白了这个本质区别,我们就不难看出下面的语句中static readonly和const能否互换了: 1. stat

  • 浅谈C++ Explicit Constructors(显式构造函数)

    C++ 为类(Class)提供了许多默认函数.如果自己没有申明,编译器会为我们提供一个copy构造函数.一个copy assignment操作符和一个析构函数.此外,如果没有申明任何构造函数,编译器会为我们申明一个default构造函数.很像下面的Empty类: class Empty{ public: Empty(); Empty(const Empty &rhs); ~Empty(); Empty& operator=(const Empty &rhs); }; 就像Effec

  • c++ 类中const成员变量的赋值方法

    在头文件的类的定义中定义了一个const成员变量c++ 规则: 1.类定义中不能进行初始化,因为头文件中类的定义只是一个声明,并没有分配真正空间,因此变量是不存在的,因此是不能赋值的. 2.const 定义的变量是不能赋值 这可如何是好,声明中不能赋值,声明完还不能赋值.又不能不赋值. 解决方案: 1.在构造函数后的参数初始化列表中初始化 2.将const变量同时声明为 static 类型进行初始化. Eg: #include <iostream> class CTestA { public:

  • 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 << "

  • JavaScript中判断变量是数组、函数或是对象类型的方法

    数组 ECMAScript5中Array.isArray是原生的判断数组的方法,IE9及以上支持.考虑到兼容性,在没有此方法的浏览器中,可以使用 Object.prototype.toString.call(obj) === '[object Array]'替代. 复制代码 代码如下: var isArray = Array.isArray || function(obj) {     return Object.prototype.toString.call(obj) === '[object

  • java中URLEncoder.encode与URLDecoder.decode处理url特殊参数的方法

    最近在使用 url 的 queryString 传递参数时,因为参数的值,被DES加密了,而加密得到的是 Base64的编码字符串 类似于: za4T8MHB/6mhmYgXB7IntyyOUL7Cl++0jv5rFxAIFVji8GDrcf+k8g== 显然 这里面含有了 特殊字符: / + = 等等,如果直接通过url 来传递该参数: url = "xxxxx?param=" + "za4T8MHB/6mhmYgXB7IntyyOUL7Cl++0jv5rFxAIFVji8

  • 如何理解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

  • c++ const引用与非const引用介绍

    const引用是指向const对象的引用. 复制代码 代码如下: const int i = 10; const int &ref = i; 可以读取ref,但不能修改.这样做是有意义的,因为i本身就不可修改,当然也不能通过ref来修改了.所以也就有将const变量赋值给非const引用是非法的. 复制代码 代码如下: int &ref1 = i; // error: nonconst reference to a const object 非const引用是指向非const类型变量的引用

  • C++中临时对象的常见产生情况及其解决的方案

    目录 前言 1. 以值传递的方式给函数传参 验证临时对象的而外开销(1) 解决方案 2. 类型转换成临时对象 / 隐式类型转换保证函数调用成功 验证临时对象的而外开销(2) 解决方案 3. 函数返回对象时候 验证临时对象的而外开销(3) 解决方案 前言 在C++中很容易就写出一些代码,这些代码的特点就是偷偷的给你产生了一些临时对象,导致临时对象会调用拷贝构造函数,赋值运算符,析构函数,假如该对象还有继承的话,也会调用父类的拷贝构造函数,赋值运算赋函数等.这些临时对象所调用的函数,都是不必要的开销

  • Angularjs中$http以post请求通过消息体传递参数的实现方法

    本文实例讲述了Angularjs中$http以post请求通过消息体传递参数的方法.分享给大家供大家参考,具体如下: Angularjs中,$http以post在消息体中传递参数,需要做以下修改,以确保消息体传递参数的正确性. 一.在声明应用的时候进行设置: var httpPost = function($httpProvider) { /******************************************* 说明:$http的post提交时,纠正消息体 ***********

  • PHP中应该避免使用同名变量(拆分临时变量)

    当一个临时变量被赋值多次时,那么将其拆分成多个,除非它是一个循环计数器. Motivation 临时变量有这多种不同的用途.比如它们可被用作循环中的计数器,在循环中保存结果集,亦或保存一个冗长的表达式的计算结果等等. 这些类型的变量(容器)应该只赋值一次.如果一个同名的临时变量被赋予多个职责,将会影响代码的可读性.这个时候我们应当引入一个新的临时变量以使代码更加清晰易懂. 可能有些注重性能的人会说,引入一个新的变量将会占用更多的内存.的确如此,但是注册一个新的变量不会吸干服务器内存的,这一点请放

  • JavaScript中的变量作用域介绍

    对于变量的作用域(scope),C.Java等语言采取的是"block scope"的方式.与之不同,JavaScript所采取的是"function scope"的方式 - 变量的作用域仅由所处的function决定,与if.for等逻辑块无关.比如,以下这个例子展示了JavaScript中与C.Java等语言不一样的行为: 复制代码 代码如下: function(){   var s = 42;//s is visible throughout function

随机推荐