我有点困惑为什么我被告知要用c ++中的二元运算符而不是foo来返回const foo。
我一直在阅读Bruce Eckel的“Thinking in C ++”,在关于运算符重载的章节中,他说“通过使[重载二元运算符]的返回值为const,你只说一个const可以为该返回值调用成员函数。这是const-correct,因为它可以防止您将潜在有价值的信息存储在最有可能丢失的对象中。“
但是,如果我有一个返回const的加号运算符和一个前缀增量运算符,则此代码无效:
class Integer{
int i;
public:
Integer(int ii): i(ii){ }
Integer(Integer&);
const Integer operator+();
Integer operator++();
};
int main(){
Integer a(0);
Integer b(1);
Integer c( ++(a + b));
}
要允许这种赋值,让+运算符返回非const值是不是有意义?这可以通过添加const_casts来完成,但这会变得非常笨重,不是吗?
谢谢!
答案 0 :(得分:4)
当你说++ x时,你说“将x加1,将结果存回x,并告诉我它是什么”。这是preincrement运算符。但是,在++(a + b)中,你如何“将结果存回到+ b”?
当然你可以把结果存回到临时表中,而临时表现在持有+ b的结果,这很快就会消失。但是如果你真的不关心结果的存储位置,你为什么要增加它而不只是添加一个呢?
答案 1 :(得分:4)
仅供参考,++(a + b)
即使使用POD(普通旧数据类型,如int
)也是非法的。因此,不允许将它用于您自己的类类型也是有意义的。试试这个:
int a = 1;
int b = 2;
int c = ++(a+b);
GCC返回error: lvalue required as increment operand
。
在您的情况下,最好让您的复制构造函数采用const Integer
参数,并改为创建您的Integer c
:
Integer c(a + b + Integer(1));
答案 2 :(得分:0)
复制构造函数通常采用 const 引用,为您解决该问题。
(非const复制ctor意味着一些资源的转移,这有时是有用的,但对于99%的情况,它是不需要的)
答案 3 :(得分:0)
我相信OP的例子适用于如果加法运算符被任何其他返回引用的二元运算符替换的问题,例如赋值运算符:
Integer c( ++(a = b));
我来到这里想知道是否应该让我的赋值运算符返回一个const或一个非const引用。 Some tutorials使用非const版本,与“Thinking in C ++”的建议相反。而且some other references给出了理由:
请注意,返回的引用未声明为const。这可能有点混乱,因为它允许你写这样的疯狂的东西:
MyClass a,b,c;
...
(a = b)= c; //什么??
乍一看,你可能希望通过让operator =返回一个const引用来阻止这样的情况。但是,像这样的语句将适用于原始类型。更糟糕的是,一些工具实际上依赖于这种行为。因此,从operator =返回非const引用非常重要。经验法则是,“如果它对于整数来说足够好,那么它对于用户定义的数据类型就足够了。”