有人可以解释这个运算符重载示例的区别,Average& operator+=(int num)
您返回对Average
的引用而不返回对Average
的引用,即Average operator+=(int num)
返回引用均值是否返回对分配给*this
的对象的引用(不是副本)。因此,在这种情况下,返回对象avg
的引用。
非参考版本如何/为何起作用?结果在哪里被复制?
#include <iostream>
#include <cstdint> // for fixed width integers
class Average
{
private:
int32_t m_total = 0; // the sum of all numbers we've seen so far
int8_t m_numbers = 0; // the count of numbers we've seen so far
public:
Average()
{
}
friend std::ostream& operator<<(std::ostream &out, const Average &average)
{
// Our average is the sum of the numbers we've seen divided by the count of the numbers we've seen
// We need to remember to do a floating point division here, not an integer division
out << static_cast<double>(average.m_total) / average.m_numbers;
return out;
}
// Because operator+= modifies its left operand, we'll write it as a member
Average& operator+=(int num)
{
// Increment our total by the new number
m_total += num;
// And increase the count by 1
++m_numbers;
// return *this in case someone wants to chain +='s together
return *this;
}
};
int main()
{
Average avg;
avg += 4;
std::cout << avg << '\n';
return 0;
}
答案 0 :(得分:2)
在C ++中覆盖运算符时,可以以多种形式提供它们。您可以定义不返回对已修改对象的引用的赋值运算符,它们将按预期工作。但是,对于每个运营商,我们都称之为a canonical implementation:
除了上面的限制之外,语言对重载运算符的作用或返回类型(它不参与重载决策)没有其他限制,但一般来说,重载运算符的行为与对于内置运算符是可能的:
operator+
应该添加而不是乘以它的参数,operator=
应该分配等等。相关运算符的行为应该类似(operator+
和operator+=
执行相同的加法操作)。返回类型受到期望使用运算符的表达式的限制:例如,赋值运算符通过引用返回以使得可以写a = b = c = d
,因为内置运算符允许这样做。通常重载的运算符具有以下典型的规范形式。
关于这些规范形式,有很多内容可以阅读,但我建议从What are the basic rules and idioms for operator overloading?上的这个非常好的答案开始
非参考版本如何/为何有效?
因为即使C ++标准鼓励您使用规范形式,也不会禁止您这样做。
复制结果在哪里?
无处,该值被丢弃。实施可能会优化它们。
答案 1 :(得分:0)
返回引用均值是否返回对分配给(不是副本)的对象的引用,该引用是* this。因此,在这种情况下,返回对象avg的引用。
是
非参考版本如何/为何起作用?结果在哪里被复制?
返回的值是传递给std::cout <<
的临时对象。
与使用相似:
int foo()
{
return 10;
}
std::cout << foo() << std::endl;
foo
的返回值是传递给std::cout <<
的临时对象。
答案 2 :(得分:0)
你应该返回一个引用,因为这是大多数代码在标准库中使用的约定,大多数程序员都这样做。大多数程序员都希望得到以下代码:
std::string s;
(s += "a") = "b";
std::cout << s << std::endl;
打印b
,或在此示例中:
int n = 10;
(n += 20) = 100;
std::cout << n << std::endl;
预计会打印100
。
这就是为什么你应该返回一个引用来保持允许修改赋值左侧的对象的约定。
否则,如果按值(副本)返回,则上述示例中的赋值将分配给临时。
答案 3 :(得分:0)
尝试检查similar question。
返回引用时,实际上是在传递实际对象。当您按值返回时,会创建临时对象,然后传递给调用者。
因此,如果您在没有参考的情况下返回,则此作业可能会按照上面的代码段进行操作
Average aa = avg += 4;
但如果你尝试,它将无法编译。
Average *ptr = &(avg += 4);
如果您返回引用,上面的代码将起作用,因为我们正在传递有效的对象范围。