const Byte operator/(const Byte& right) const {
require(right.b != 0, "divide by zero");
return Byte(b / right.b);
}
我读到如果运算符的效果是产生一个新值,则需要生成一个新对象作为返回值。例如,Integer::operator+
必须生成一个Integer
对象,它是操作数的总和。此对象按值const
返回,因此无法将结果修改为左值。
如果我们不将其写为const
怎么办?任何有解释的例子都会有所帮助。
为什么我们在函数原型中有第二个const
?
答案 0 :(得分:5)
任何有解释的例子都会有所帮助。
这是过时的建议,旨在使操作员的行为有点像内置操作符,以便像(a / b) = c
这样的废话不会编译。
但是,从C ++ 11开始,它也会抑制移动语义,这会影响效率;所以你不应该返回const
值。
为什么我们在函数原型中有第二个const?
参数是const
引用,成员函数是const
,以(a)确保运算符不修改任一操作数; (b)允许用恒定或临时操作数调用它。
详细说明(b),如果没有这些const
限定符,你将无法使用常量操作数:
const Byte a, b;
a / b; // ERROR: operands can't be const
或临时值:
Byte f();
f() / f(); // ERROR: operands can't be temporary
答案 1 :(得分:1)
对于二进制运算符,我更喜欢定义一个“自由”(非成员)函数(可能是它所运行的类的friend
,以备它需要时直接访问该类的private
或protected
数据成员:
class Byte {
....
friend Byte operator/(const Byte& left, const Byte& right) {
require(right.b != 0, "divide by zero");
return Byte(left.b / right.b);
}
};
left
和right
参数均由const &
传递,因为:
const
&
无论如何,如果您的Byte
类只包含一个8位字节,并且复制构造函数是一个简单的单字节副本,那么您可以简化代码并只是按值传递 :
friend Byte operator/(Byte left, Byte right) {
require(right.b != 0, "divide by zero");
return Byte(left.b / right.b);
}