【发布时间】:2023-03-12 15:45:01
【问题描述】:
在阅读了 Scott Meyers 的《More Effective C++》一书的第 20 和 22 条后,我决定提出这个问题。
假设你写了一个类来表示有理数:
class Rational
{
public:
Rational(int numerator = 0, int denominator = 1);
int numerator() const;
int denominator() const;
Rational& operator+=(const Rational& rhs); // Does not create any temporary objects
...
};
现在假设您决定使用operator+= 实现operator+:
const Rational operator+(const Rational& lhs, const Rational& rhs)
{
return Rational(lhs) += rhs;
}
我的问题是:如果返回值优化被禁用,operator+会创建多少临时变量?
Rational result, a, b;
...
result = a + b;
我相信创建了 2 个临时对象:一个是在 operator+ 的主体内执行 Rational(lhs) 时,另一个是通过复制第一个临时对象创建 operator+ 返回的值。
当 Scott 介绍这个操作时,我产生了困惑:
Rational result, a, b, c, d;
...
result = a + b + c + d;
并写道:“可能使用 3 个临时对象,每次调用 operator+ 一个”。我相信如果 返回值优化 被禁用,上面的操作将使用 6 个临时对象(每个调用 operator+ 2 个),而如果它被启用,上面的操作将不使用临时对象一点也不。斯科特是如何得出他的结果的?我认为这样做的唯一方法是部分应用返回值优化。
【问题讨论】:
-
您可以检测析构函数(让它打印一些东西),这样可以计算编译器实际创建了多少临时对象。但是,您很难找到可以禁用 RVO 的编译器。我所知道的所有现代编译器都无条件执行它,即使在禁用优化的调试版本中也是如此。此外,C++17 标准规定 RVO 是强制性的,这使得这个问题毫无意义。
-
这是一个很好的问题 (+1),但我非常不喜欢这种情绪。您是在问“如果禁用 C++ 的即将成为强制性的”功能会发生什么?
-
operator+ 会创建多少个临时变量 -- 这是否真的取决于编译器,即使您能够关闭 RVO?一个“坏”的编译器可能比一个“好的”编译器创建更多的临时文件,但仍能达到相同的最终结果。
-
@Bathsheba -- 如果 OP 的引用是正确的,看起来甚至 Scott M. 都不确定 -- 可能使用 3 个临时对象, --关键字是“可能”。
-
@user3266738:仅供参考:“如果禁用了返回值优化,operator+ 会创建多少临时变量?”如果 RVO 被禁用,则创建的数量相同已启用。
标签: c++ operator-keyword copy-elision return-value-optimization effective-c++