引用和常量引用作为函数参数的区别?

Posted

技术标签:

【中文标题】引用和常量引用作为函数参数的区别?【英文标题】:Difference between reference and const reference as function parameter? 【发布时间】:2009-11-12 04:08:25 【问题描述】:

这是一个简单的C++代码sn-p:

A foo()
  A a; // create a local A object
  return a;


void bar(const A & a_r)



bar(foo());

为什么函数 bar 的参数必须是 const 引用,而不仅仅是引用?

Edit1:我知道引用是为了避免复制开销。和 const 是只读的。但是这里我必须让它成为一个const引用,否则如果我删除“const”,g++会向我抛出一个错误。

Edit2:我的猜测是 foo() 的返回对象是一个临时对象,不允许更改临时对象的值?

【问题讨论】:

它的函数本身决定它的参数是否应该是const。换句话说,你应该提供bar的内容。 【参考方案1】:

如果没有错误消息,我不确定编译器可能会抱怨什么,但我可以从逻辑上解释原因:

行内:

bar(foo()); 

foo()的返回值是一个临时的A;它是通过调用 foo() 创建的,然后在 bar() 返回时立即销毁。执行非常量操作(即更改临时 A 的操作)没有意义,因为对象 A 之后立即被破坏。

再看一点,这是这个问题的虚拟副本:

How come a non-const reference cannot bind to a temporary object?

答案很好。

【讨论】:

A 类对象的副本被返回,这将在 bar() 中可见。 谢谢,这实际上是我的猜测 :)。所以它是非法的,只是因为改变临时对象没有意义? wei - 没错,C++ 标准不赞成更改临时对象。同样,我链接的问题的解释比我写的要好得多。 :-)【参考方案2】:

引用必须引用const 对象,因为无论如何您都无法使用对它的更改。对比以下代码sn-ps:

void bar(A&);   
A x = foo();
bar(x);
if (x.member) ... else ...

void bar(A const&);   
bar(foo());
if (//x? we don't have any x! We can't branch here!

虽然在第一个示例中,修改对象的能力可能会显着改变后续代码的执行,但在第二个示例中,我们只是没有方法(我们可以参考变量名)来做到这一点。因此,我们只能使用对 const 的引用,它希望对象不被修改。

【讨论】:

【参考方案3】:

为什么函数bar的参数 必须是一个常量引用,而不仅仅是 参考?

bar() 的参数不必是 const 引用。但是在将对象传递给函数参数时,当对象不会被函数修改时,这是最有效的方式。

将参数设为常量可确保编译器在您尝试修改对象时发出警告。 将参数作为引用传递不会创建对象的副本,因此可以提高效率。

【讨论】:

【参考方案4】:

编译器正在寻找bar(const foo&),因为您将const reference to foo 传递到bar(foo()) 中的bar - 这是因为您正在传递对一个临时变量的引用,该变量在bar 返回后将不存在。

没有任何用例可以通过引用在bar 中修改foo,因为一旦从bar() 返回,它就不会存在。

因此编译器强制执行此操作以防止开发人员将引用传递给临时对象并更新将在方法返回后消失的临时对象的隐藏错误。

【讨论】:

【参考方案5】:

代码 bar(foo()) 将左值传递给 bar()。只有右值可以有一个指针或引用它。左值可以有一个 const 引用,因为 const 限制阻止了对不存在的左值的赋值操作。

【讨论】:

以上是关于引用和常量引用作为函数参数的区别?的主要内容,如果未能解决你的问题,请参考以下文章

C#在方法调用中,参数按值传递与按引用传递的区别是啥?

我们是不是应该在函数的参数中使用常量类型引用? [复制]

引用与指针的区别

在c语言中子函数引用主函数中的值和引用主函数某个值的地址的区别

传指针和传指针引用的区别/指针和引用的区别(本质)

为 const 引用和 rvalue 引用编写重载