C ++返回值,引用,const引用

时间:2014-02-14 11:23:05

标签: c++ reference const-reference return-by-reference return-by-value

你能解释一下返回值,引用值和const引用值之间的区别吗?

值:

Vector2D operator += (const Vector2D& vector)
{
    this->x += vector.x;
    this->y += vector.y;
    return *this;
}

非常规参考:

Vector2D& operator += (const Vector2D& vector)
{
    this->x += vector.x;
    this->y += vector.y;
    return *this;
}

Const参考:

const Vector2D& operator += (const Vector2D& vector)
{
    this->x += vector.x;
    this->y += vector.y;
    return *this;
}

这有什么好处?我理解const引用传递给函数背后的意义,因为你要确保不要修改引用指向函数内部的这个值。但我对返回const引用的含义感到困惑。为什么返回引用比返回值更好,为什么返回const引用要比返回非const引用更好?

5 个答案:

答案 0 :(得分:19)

除非你写一些奇怪的东西,如

,否则没有区别
(v1 += v2) = v3;

在第一种情况下,作业将是临时的,整体效果将是v1 += v2

在第二种情况下,作业将转移到v1,因此整体效果将为v1 = v3

在第三种情况下,不允许转让。这可能是最好的选择,因为这种怪异几乎肯定是一个错误。

  

为什么返回引用比返回值更好?

它可能更有效:您不必复制该对象。

  

为什么返回const引用比返回not-const引用要好?

您可以像上面的示例一样防止出现奇怪现象,同时仍然允许不那么奇怪的链接,例如

v1 = (v2 += v3);

但是,如评论中所述,这意味着您的类型不支持与内置类型相同的(ab)使用形式,这是某些人认为合适的。

答案 1 :(得分:10)

<强>值:

按值返回意味着您要返回对象的副本。这就要求对类(它必须是可复制的或可移动的)的要求。这意味着对于按值返回的某些类的对象可能是昂贵的(在RVO或NRVO不起作用或关闭的情况下)。这也意味着新对象与其他对象是独立的(取决于其设计),并且是它自己的值。这可能是你应该从许多二元运算符返回的,如+, - ,*等等。

非常规参考:

你真的为另一个对象返回一个别名。别名为非const允许您修改别名对象。这是你应该从一些一元的操作符返回的内容,比如前缀++和 - ,以及*(取消引用),因为你通常希望能够修改返回的对象。

由运营商&gt;&gt;返回和运算符&lt;&lt;为溪流重载。这允许操作员链接:

cout << 5 << "is greater then" << 1 << endl;
cin >> myInt >> myFloat;

如果要允许链接常规方法,也可以返回* this的引用:

object.run().printLastRunStatistics();

Const参考:

如上所述,但您无法修改别名对象。当要返回的对象复制起来很昂贵,并且在从函数返回后可以确保它存在时,可以使用而不是按值返回。

这就是operator =通常以标准类型支持它们的方式返回以允许多个赋值:

a = b = c;

operator =中使用的const-reference阻止了这种用法(据我记忆,标准类型不支持):

++(a = b);
如果使用正常参考,则允许

答案 2 :(得分:5)

与将函数传递给函数完全相同。

当您返回对象的属性时,您希望返回const引用,并且不希望在其外部修改它。例如:当您的对象具有名称时,您可以使用以下方法const std::string& get_name(){ return name; };。哪种方式最佳。您允许对内部属性进行“只读”访问,而无需复制返回。

当你重载运算符时,你应该返回一个可变的对象,否则一些通常可以使用的某些语法会产生错误。当你尝试一些奇怪的链接时,这是非常重要的。

例如,选项3不适用于(v1 += v2).non_const_method()之类的内容,而以下是:

v1+=v2;
v1.non_const_method();

答案 3 :(得分:4)

按值返回按引用返回之间的差异在运行时生效:

当您返回一个按值的对象时,将调用该复制构造函数,并在该堆栈上创建一个临时实例。

当您按引用返回对象时,不会发生上述所有操作,从而提高性能。


按引用返回按引擎返回之间的差异没有运行时效果,只是为了保护您免于编写错误代码。

例如,使用Vector2D& operator += (const Vector2D& vector),您可以执行以下操作:

(x+=y)++(x+=y).func()其中func是类Vector2D中的非const函数。

但是对于const Vector2D& operator += (const Vector2D& vector),编译器会为任何类似的尝试生成错误。

答案 4 :(得分:1)

正如所指出的那样但是luk32只是为了确保不允许对此函数返回的对象进行任何更改。 这基本上可以帮助您在编译时找到逻辑错误。 假设您确定不更改对象,并且您的代码正在更改对象,则可以对其进行跟踪。可以认为它是一种很好的编码实践。