专栏首页C/C++基础临时变量作为非const的引用进行参数传递引发的编译错误

临时变量作为非const的引用进行参数传递引发的编译错误

1.错误原因即解决办法

Linux环境运行,使用g++编译,观察如下代码,会出现: invalid initialization of non-const reference of type ‘std::string&’ from a temporary of type ‘std::string’的错误。

其中文意思为临时变量无法为非const的引用初始化。也就是在参数传递的过程中,出现错误。出错的代码如下:

void print(string& str)
{
    cout<<str<<endl;
}
//如此调用会报上面描述的错误
print("hello world");

出错的原因是编译器根据字符串”hello world”构造一个string类型的临时对象,这个临时对象具有const属性。当这个临时对象传递给非const的string&引用类型时,因为非const引用绑定对象时,要求该对象也是非const对象。而在这时,因为string类型的临时对象是const对象,所以就出现错误。因此,解决办法就是将print()函数的参数改为常引用。代码修改如下,可顺利通过编译。

void print(const string& str)
{
    cout<<str<<endl;
}
//顺利通过编译
print("hello world");

通过以上代码,也可以看出Effective C++中倡导的一个C++的编程原则,即尽可能的使用const。因为这样可以使代码更为健壮,将错误暴露于编译阶段。


2.所有的临时对象都是const对象吗

为什么临时对象作为引用参数传递时,必须是常量引用呢?很多人对此的解释是临时对象是常量,不允许赋值改动,所以作为非常量引用传递时,编译器就会报错。这个解释在关于理解临时对象不能作为非const引用参数这个问题上是可以的,但不够准确。更有甚者,认为所有的临时对象均是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;
}

//打印函数
void print(IntClass & intc)
{
    cout<<intc<<endl;
    //通过引用修改这个临时对象
    intc=8;
    cout<<intc<<endl;
}

int main(int argc,char* argv[])
{
    print(IntClass(6));
}

程序输出: 6 8

以上代正确编译运行,没有错误。IntClass(6)表示生成一个无名的临时对象,传递给非const引用,在print函数中通过引用修改了这个临时对象。这说明了并非所有的临时对象都是const对象

那哪些临时对象是const对象,哪些临时对象不是const对象呢?这里贴上摘自网上的一句话:“内置类型产生的临时变量具有常性,而自定义类型产生的临时变量不具有常性”,我想这句话能解释你所谓的临时变量为什么能作为左值的原因。”此话不知正确与否,但目前还没有发现其错误,待以后考证。


参考文献

[1]http://blog.sina.com.cn/s/blog_4cce4f6a0100piuv.html

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • C/C++ const

    const是C语言的关键字,经C++扩充,功能变得强大,用法复杂。const用于定义一个常变量(只读变量)。当const与指针、引用、函数等结合起来使用时,情况...

    Dabelv
  • C++临时变量的常量性

    在Linux环境使用g++编译,会出现: invalid initialization of non-const reference of type ‘std:...

    Dabelv
  • Linux命令(26)——rename命令

    功能类似于mv,可实现文件或者目录的重命名,mv不能批量处理,而rename可以。

    Dabelv
  • 浅谈前端JavaScript编程风格

    前言 多家公司和组织已经公开了它们的风格规范,具体可参阅jscs.info,下面的内容主要参考了Airbnb的JavaScript风格规范。当然还有google...

    xiangzhihong
  • Qt编写自定义控件33-图片切换动画

    在很多看图软件中,切换图片的时候可以带上动画过渡或者切换效果,显得更人性化,其实主要还是炫一些,比如百叶窗、透明度变化、左下角飞入等,无论多少种效果,核心都是围...

    feiyangqingyun
  • Spring Boot 静态资源处理

    以前做过web开发的同学应该知道,我们以前创建的web工程下面会有一个webapp的目录,我们只要把静态资源放在该目录下就可以直接访问。

    IT大咖说
  • body标签中相关标签

    字体标签包含:h1~h6、<font>、<u>、<b>、<strong><em>、<sup>、<sub>

    py3study

扫码关注云+社区

领取腾讯云代金券