目录
  1. 举例
  2. 分析
  3. 解决
1、举例

非常量引用 指向 临时对象 —— 即:将 临时对象 传递给 非常量引用类型。

如以下情况就会出现:

实现实数Rational类,实数可以使用+号相加,运算的结果要可以使用 "cout << " 以分数形式输出 实数Rational 的值:

    Rational a(,);
Rational b(,);
cout << a+b << endl;

在这里需要重载2个操作符函数:“+”号 和  “<<” 输出符号

//在Rational类中定义如下
friend ostream &operator<< (ostream& outs,Rational &rational);
Rational operator+(Rational &secondRational);

在这种定义下,就会出现我们所要说的问题:非常量引用不能指向临时对象。

a+b 函数返回一个Rational类的临时对象;而 << 操作函数的参数却是 Rational & rational 。这种情况函数会报错如下:

    no match for 'operator<<' in 'std::cout << a.Rational::operator+(((Rational&)(& b)))'

虽然定义了 operator<< 。但是编译器对 a+b 返回的临时对象不买单,直接报了个“没有匹配的函数” 的错误。

2、分析

以C++的语义来说,如果一个程序员只想传递参数给函数,而不希望函数修改传入的参数时,那么,或者使用值传递,或者采用常量型引用。考虑到大对象复制时产生的开销,一般使用常量型引用const &。如果函数的参数是某个类型的一个非常量的引用,那就相当于告诉编译器,程序员希望得到函数对参数的修改结果。
临时变量是由编译器生成的,C++语言规范没规定编译器生成临时变量的规则,程序员无法得知由编译器生成的临时变量的名字,程序员无法访问那个临时变量。这意味着,以引用的方式传递一个临时变量做为函数参数,如果函数内部对此临时变量做了修改,那么函数返回后,程序员无法获得函数对临时变量的修改。函数对临时变量所做出的所有更改,都将丢失。
一方面,在函数申明中,使用非常量型的引用告诉编译器你需要得到函数对某个对象的修改结果,可是你自己又不给变量起名字,直接丢弃了函数的修改结果,编译器只能说:“大哥,你这是干啥呢,告诉我把结果给你,等我把结果给你了,你又直接给扔了,你这不是在玩我吗?”

同时,C++的标准 为了防止给常量或临时变量(只有瞬间的生命周期)赋值(易产生bug),只许使用const引用之。

3、解决
friend ostream &operator<< (ostream& outs,Rational &rational);  //非常量引用

改为值传递:

ostream &operator<<(ostream &outs, Rational ratiaonl)       //值传递

改为常量引用:

ostream &operator<<(ostream &outs,const Rational &rational) //常量引用

C++ —— 非常量引用不能指向临时对象的更多相关文章

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

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

  2. C++ 非常量引用无效

    /* 非常量引用无效 */ #include <iostream> using namespace std; /* C++标准的规定:非常量的引用不能指向临时对象: 为了防止给常量或临时变 ...

  3. c++产生非常量引用的初始值必须是左值

    出现这种情况是因为调用函数的形参类型是  T&(T为某一类型),该类型与调用参数值传入不一致,比如函数中形参是int型,而传入实参是double,存在隐式类型转化,系统会自动产生临时变量tem ...

  4. Python3标准库:weakref对象的非永久引用

    1. weakref对象的非永久引用 weakref模块支持对象的弱引用.正常的引用会增加对象的引用数,并避免它被垃圾回收.但结果并不总是如期望中的那样,比如有时可能会出现一个循环引用,或者有时需要内 ...

  5. 常量函数、常量引用参数、常量引用返回值[C++]

    1. 关于常量引用正像在C语言中使用指针一样,C++中通常使用引用 有一个函数... foo()并且这个函数返回一个引用...... & foo()...., 一个指向位图(Bitmap)的引 ...

  6. 临时对象与NRV技术

    <More Effective C++>中讲到,在C++中真正的临时对象是看不见的,它们不出现在你的源代码中.建立一个没有命名的非堆(non-heap)对象会产生临时对象,这种未命名的对象 ...

  7. C++临时对象的生命期

    class Test{ public: Test(int a):m_int(a){ printf("this is Test(%d) ctor\n", m_int); } ~Tes ...

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

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

  9. 不可或缺 Windows Native (18) - C++: this 指针, 对象数组, 对象和指针, const 对象, const 指针和指向 const 对象的指针, const 对象的引用

    [源码下载] 不可或缺 Windows Native (18) - C++: this 指针, 对象数组, 对象和指针, const 对象,  const 指针和指向 const 对象的指针, con ...

随机推荐

  1. Servlet学习--练习示例总结

    醉了醉了..本来想测试下Servlet生命周期的,然后调了好久的错误,还是没成功,不知道为什么不能这样做 贴上代码: import java.io.IOException; import java.i ...

  2. Android onConfigurationChanged(Configuration cfg) 无法触发问题

     1.android:configChanges="orientation|keyboardHidden"的使用  当在activity加上android:configChange ...

  3. Swift - 31 - 常量参数, 变量参数和inout参数

    //: Playground - noun: a place where people can play import UIKit // swift中默认情况下, 传入的参数是不可以修改的, 也就是l ...

  4. PHP MySQL 预处理语句

    PHP MySQL 预处理语句 预处理语句对于防止 MySQL 注入是非常有用的. 预处理语句及绑定参数 预处理语句用于执行多个相同的 SQL 语句,并且执行效率更高. 预处理语句的工作原理如下: 预 ...

  5. cas sso单点登录系列5_cas单点登录增加验证码功能完整步骤

    转:http://blog.csdn.net/ae6623/article/details/8919718 本篇教程cas-server端下载地址:解压后,直接放到tomcat的webapp目录下就能 ...

  6. GitHub-修改以下host-ip可加快访问速度

    #GitHub START 207.97.227.239    github.com 204.232.175.94    gist.github.com 107.21.116.220    help. ...

  7. Python文件处理之文件指针(四)

    当我们读取文件内容时,并不能重复的读取,比如一个blogCblog.txt文件里有blogCblog内容,用两个read()方法读取blogCblog.txt的内容,会发现,第一个返回文件内容,第二个 ...

  8. java 代码格式(转)

    //转至博客:http://developer.51cto.com/art/201202/320317.ht /** * Java编码格式个人推荐,参考JDK源码和Hyperic HQ源码(原spri ...

  9. C++ Primer chap7

    /* 第七章7.1: */ //#include<iostream> //#include<string> //using std::cin; //using std::cou ...

  10. No Entity Framework provider found for the ADO.NET provider with invariant name 'System.Data.SqlClient'

    运行代码是出现了这个错误,No Entity Framework provider found for the ADO.NET provider with invariant name 'System ...