C++ 运算符 += 重载返回引用
c++ operator += overloading return reference to
有人可以解释一下这个运算符重载示例中的区别是什么,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;
}
你应该返回一个引用,因为这是标准库中大多数代码使用的约定,大多数程序员都这样做。大多数程序员会期望以下代码:
std::string s;
(s += "a") = "b";
std::cout << s << std::endl;
打印b
,或在此示例中:
int n = 10;
(n += 20) = 100;
std::cout << n << std::endl;
将期望打印100
。
这就是为什么你应该返回一个引用以保持约定,该约定允许修改位于赋值左侧的对象。
否则,如果您按值(副本)返回赋值,如上例所示将分配给临时。
在 C++ 中重写运算符时,可以以多种形式提供它们。您可以定义不返回对已修改对象的引用的赋值运算符,它们将按预期工作。但是,对于每个运算符,我们都有所谓的规范实现:
除了上述限制之外,该语言对重载运算符的操作或返回类型(它不参与重载解析)没有其他约束,但通常,重载运算符的行为应尽可能类似于内置运算符:
operator+
期望添加而不是乘以其参数,operator=
应分配等。相关运算符的行为应该类似(operator+
并且operator+=
执行相同的类似加法的操作)。返回类型受到预期使用运算符的表达式的限制:例如,赋值运算符通过引用返回以使其可以写入a = b = c = d
,因为内置运算符允许这样做。通常重载运算符具有以下典型的规范形式。
关于这些规范形式有很多东西要读,但我建议从这个非常好的 SO 答案开始 运算符重载的基本规则和习语是什么?
非参考版本如何/为什么工作?
因为即使C++标准鼓励您使用规范形式,它也不会禁止您不使用规范形式。
结果被复制到哪里?
无处可去,该值将被丢弃。实施可能会优化它们。
返回引用是否意味着返回对被分配到的对象(而不是副本)的引用,即 *this。因此,在本例中返回对对象 avg 的引用。
是的。
非参考版本如何/为什么工作?结果被复制到哪里?
返回值是传递给std::cout <<
的临时对象。
这类似于使用:
int foo()
{
return 10;
}
std::cout << foo() << std::endl;
foo
的返回值是传递给std::cout <<
的临时对象。
尝试检查这个类似的问题。
当您返回引用时,您实际上是在传递实际对象。而当您按值返回时,将创建临时对象,然后将其传递给调用方。
因此,如果您在没有引用的情况下返回,则此分配可能会按照上面的代码段工作。
Average aa = avg += 4;
但是如果你尝试,它将无法编译。
Average *ptr = &(avg += 4);
如果您返回引用,上面的代码将起作用,因为我们正在传递有效的对象范围。
- 寿命延长从函数返回引用
- 了解C++如何返回引用并绑定到引用
- 返回引用实例和非引用实例(return mystr & vs mystr)之间的区别是什么?
- 从类返回引用向量
- 使用unique_ptr并返回引用,或者我应该使用shared_ptr并在需要时制作副本
- 混淆C++从函数返回引用
- 两个相同的重载运算符[]一个返回引用
- 为什么向量的.at()成员函数返回引用而不是迭代器
- C++使用和返回引用
- 返回 T 引用的 Const 函子禁止赋值
- 返回引用是否也会延长其生存期?
- 如何返回引用,然后递增迭代器
- 如果使用返回引用的函数初始化"auto"var,为什么它不声明引用类型?
- 我是否需要将 ref 与 make_pair 一起使用才能返回引用?
- 在 vector::at 返回引用后进行更改
- 为什么PyImport_ImportModule返回引用计数为 3 而不是 1 的 PyObject*
- 超出返回引用的单一实例生存期
- Boost.Python 返回引用现有 c++ 对象的 python 对象
- C++ 运算符 += 重载返回引用
- 如何声明接受转发引用并返回引用或副本的函数模板