返回值,引用,常量引用

你能给我解释一下返回值、参考值和常量参考值之间的区别吗?

价值:

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 Vector2D& operator += (const Vector2D& vector)
{
this->x += vector.x;
this->y += vector.y;
return *this;
}

这样做有什么好处?我理解将常量引用传递给函数背后的含义,因为您希望确保不要修改函数内部引用所指向的值。但是我对返回 const 引用的含义感到困惑。为什么返回引用比返回值好,为什么返回常量引用比返回非常量引用好?

114710 次浏览

没什么区别,除非你写些奇怪的东西

(v1 += v2) = v3;

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

在第二种情况下,赋值将是 v1,因此总体效果将是 v1 = v3

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

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

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

为什么返回常量引用比返回非常量引用好?

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

v1 = (v2 += v3);

但是,正如注释中指出的那样,这意味着您的类型不支持与内置类型相同的(ab)使用形式,有些人认为内置类型是可取的。

它与向函数传递参数完全相同。

当您返回一个对象的属性时,您希望返回一个 const引用,而您不希望在该对象之外修改该属性。例如: 当对象具有名称时,可以使用以下方法 const std::string& get_name(){ return name; };。这是最理想的方式。您允许对内部属性进行“只读”访问,而不允许返回时进行复制。

当您重载运算符时,您需要返回一个可变的对象,否则某些通常可以工作的特定语法将产生错误。当你尝试一些奇怪的锁链时,这是非常重要的。

例如,选项3将不适用于类似 (v1 += v2).non_const_method()的东西,而下面的选项将:

v1+=v2;
v1.non_const_method();

正如前面提到的,luk32只是为了确保不允许对这个函数返回的对象进行更改。 这基本上可以帮助您在编译时查找逻辑错误。 假设您确定不更改对象,并且您的代码正在更改该对象,则可以跟踪该对象。这可以被认为是一个很好的编码实践。

按价值计算的回报率按参考资料提交报税表之间的差异在运行时生效:

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

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


按参考资料提交报税表按常数返回的引用之间的差异没有运行时效应,只是为了防止您编写错误代码。

例如,使用 Vector2D& operator += (const Vector2D& vector),您可以:

(x+=y)++(x+=y).func(),其中 funcVector2D类中的非常量函数。

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

价值:

通过值返回意味着您正在返回一个对象的副本。这就对类提出了要求(它必须是可复制的或可移动的)。这意味着对于某些类的对象来说,通过值返回可能是昂贵的(在 RVO 或 NRVO 不工作或被关闭的情况下)。这也意味着新对象独立于其他对象(取决于它的设计) ,并且是它自己的值。这可能是您应该从许多二进制运算符(如 + 、-、 * 等)返回的结果。

非常规参考文献:

实际上返回的是另一个对象的别名。非常量别名允许您修改带别名的对象。这就是一元运算符(比如前缀 + + 和——)和 * (解引用)应该返回的内容,因为您通常希望能够修改返回的对象。

这由操作符 > > 和操作符 < < 重载的流返回。这允许操作符链接:

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

当您希望允许像下面这样链接常规方法时,还可以返回对 * this 的引用:

object.run().printLastRunStatistics();

参考文献:

如上所述,但你不能修改别名对象。当要返回的对象的复制开销很大,并且在从函数返回后可以确保它的存在时,可以使用。

这就是运算符 = 通常返回的,以标准类型支持的方式允许多个赋值:

a = b = c;

操作符 = 中使用的 Const 引用可以防止这种使用(据我所知,标准类型不支持这种使用) :

++(a = b);

如果使用正常引用则允许。