你能解释一下返回值,引用值和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引用更好?
答案 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只是为了确保不允许对此函数返回的对象进行任何更改。 这基本上可以帮助您在编译时找到逻辑错误。 假设您确定不更改对象,并且您的代码正在更改对象,则可以对其进行跟踪。可以认为它是一种很好的编码实践。