摘要:

    非const 引用形参只能与完全同类型的非const对象关联。

     具体含义为:(1)不能用const类型的对象传递给非const引用形参;

                   (2)实参类型必须与非const引用形参的类型完全一致,例如,不可以将一个float对象传给 double &类型的引用形参;

                       (3)不能将一个右值类型的实参 传递给 非const引用形参。

  

      建议:在不需要修改实参的值的前提下,尽量使用const 限定的引用作为形参。

C++中的引用传参是给实参起了一个别名,这种参数传递方法称为按引用传递。按引用传递允许被调用的函数能够访问调用函数中的变量。
但是如果函数的实参是一个表达式而不是一个左值的时候,会发生什么情况呢。
如果有一个函数:

double square(const double &ra) {
return ra * ra;
}

如果试图使用square(x + 3.0)这样的调用,将发生什么情况呢?在现代版本的C++中,这是错误的,有些编译器将指出这一点;有些编译器将发出这样一个警告:

Warning: Temporary used for parameter 'ra' in call to square(double &)

因为早期的C++确实允许将表达式传递给引用变量。那么,它的实现方式是:x+3.0不是double类型的变量,因此程序将创建一个临时的无名变量,并将其初始化为表达式x+3.0的值。然后,ra将成为该临时变量的引用。下面详细看看这种情况:
如果实参与引用参数不匹配,C++将生成临时变量。现在,仅当参数为const引用时,C++才允许这样做,但是这是一种新的限制。它会在以下两种情况下生成临时变量:

  • 实参的类型正确,但不是左值。
  • 实参的类型不正确,但可以转换为正确的类型。

左值是可被引用的数据对象,例如,变量、数组元素、结构成员、引用和被解除引用的指针都是左值。非左值包括字面常量和包含多项的表达式。对于函数:

double square(const double &ra) {
return ra * ra;
}

现在考虑如下代码:

double side = 3.0;
double *pd = &side;
double &rd = side;
long edge = 5L;
double lens[4] = {2.0, 3.0, 4.0, 5.0};
double c1 = square(side); //ra is side
double c2 = square(lens[2]); //ra is lens[2];
double c3 = square(rd); //ra is rd is sizd
double c4 = square(*pd); //ra is *pd is side
double c5 = square(edge); //ra is temporary variable
double c6 = square(7.0); //ra is temporary variable
double c7 = square(side + 7.0) //ra is temporary variable

参数side, lens[2], rd, *pd都是有名称的、double类型的数据变量,因此可以创建引用。但是,edge属于不同类型的变量,7.0是常量类型,side+7.0属于表达式,在这几种情况下编译器都会生成一个临时变量,并让ra引用它。
C++允许常量引用对于这种行为(建立临时变量),是因为该函数的目的是使用传递的值,而不是修改它们,因此创建临时变量不会造成任何不利的影响,反而会使函数在可处理的参数种类方面更通用。实际上,对于形参为const引用的C++函数,如果实参不匹配,刚其类似于按值传递,为确保原始数据不改变,使用临时变量来存储值。

Reference

[1] <C++ premier >中文版第四版 7.2.2节

[2] 引用传参、临时变量和const  http://gzxabcdefg.blog.163.com/blog/static/2345179420118308105747/

临时变量不能作为非const类型引用形参的实参的更多相关文章

  1. 临时变量不能作为非const引用

    转自:http://blog.csdn.net/u011068702/article/details/64443949 1.看代码 2.编译结果 3.分析和解决 就拿f(a + b)来说,a+b的值会 ...

  2. 非const引用参数传入不同类型编译不过的理解(拒绝将临时对象绑定为非const的引用的形参是有道理的)

    int f (int & I) { cout<<I<<std::endl; } void main() { long L; f(L); // 编译不过 f((int)L ...

  3. const变量指针赋值给非const类型的指针运行结果

    在c++可以定义一个const变量,然后把变量的值赋给一个非const指针,可以通过指针来改变const变量的值吗?下面的截图给出了答案

  4. C++11引用临时变量的终极解析

    工作中遇到一个引用临时变量的问题,经过两天的学习,私以为:不仅弄明白了这个问题,还有些自己的独到见解. 这里使用一个简单的例子来把自己的学习过程和理解献给大家,如果有什么问题请不吝指正.   **** ...

  5. const类型总结

    const 表示常类型   作用: 1.具有不可变性.   2.可以很方便对参数进行调整和修改,和宏定义一样,不变则已,变都变.   3.保护被修饰的东西,防止被意外修改.(如:在修饰函数的形参时,加 ...

  6. C++临时变量的生命周期

    C++ 中的临时变量指的是那些由编译器根据需要在栈上产生的,没有名字的变量.主要的用途主要有两类: 1) 函数的返回值, 如: string proc() { return string(" ...

  7. [转] C++临时变量的生命周期

    http://www.cnblogs.com/catch/p/3251937.html C++中的临时变量指的是那些由编译器根据需要在栈上产生的,没有名字的变量. 主要的用途主要有两类: 1) 函数的 ...

  8. 非const引用不能指向临时变量

    没找到具体原因,MSDN看到下面这句,VC是从2008才有这一限制的,感觉就是从语法上对临时变量增加了限定,因为一般说来修改一个临时变量是毫无意义的,通过增加限定,强调临时变量只读语义.虽然实际上修改 ...

  9. C++-const_cast只能用于指针和引用,对象的const到非const可以用static_cast

    Static_cast可以对对象也可以对指针也可以对引用,但是const_cast只可以对指针和引用使用,后者不可以对对象用,如果你要把一个const值转化为非const值只能用隐式执行或通过使用st ...

随机推荐

  1. 移动端设页面根目录HTML的字体大小

    @media (max-width: 359px){ html { font-size: 62.5%; }}@media (min-width: 360px) and (max-width: 374p ...

  2. 上传文件报错System.Net.ProtocolViolationException: 必须先将 ContentLength 字节写入请求流,然后再调用 [Begin]GetResponse。

    在上传文件的时候报错. 错误: System.Net.ProtocolViolationException: 必须先将 ContentLength 字节写入请求流,然后再调用 [Begin]GetRe ...

  3. DataStage

    parallel job shell调用:dsjob ./dsjob -run -mode NORMAL -paramfile xxx.param <PROJECT> <JOB> ...

  4. WebLogic部署

    1.抓取解压WAR包,放在相应目录下 2.登录部署,激活 http://jingyan.baidu.com/article/c74d6000650d470f6b595d72.html Linux环境中 ...

  5. K3问题 无法创建中间层 组件<KdSvrMgr>无法正常工作

    K3遇到如下问题 一直无法解决,这个是本地计算机的问题,跟服务器没关系,采用笨方法,重装K3(重装到本磁盘.其他磁盘),重装系统,虽然笨,但最后都解决掉了

  6. JS判断客户端是手机还是PC的2个代码(转)

    转载自:http://www.jb51.net/article/48939.htm Javascript 判断客户端是否为 PC 还是手持设备,有时候项目中需要用到,很方便的检测,源生的哦,方法一共有 ...

  7. C#传真传址 结构体

    1.传真  传址 namespace 传值_传址 { class Program { //格式1:无参无返 public void LeiJia() { Console.Write("请输入 ...

  8. QL Server 实用脚本

    use MyFirstDB; -- 主要内容 -- SQL Server 实用脚本 -- 1.case语句 -- 2.子查询 -- 3.连接查询 -- 4.脚本变量与流程控制(选择与循环等) -- 5 ...

  9. java导出excel(解决导出几万条数据内存溢出的问题)

    import java.io.BufferedOutputStream; import java.io.DataOutputStream; import java.io.File; import ja ...

  10. Jquery选中行实现行中的Checkbox的选中与取消选中

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs& ...