重载的递增运算符返回值

3
在《C++程序设计语言》一书中,Stroustrup提供了以下关于增量/减量运算符重载的示例:
class Ptr_to_T {
    T* p;
    T* array ;
    int size;
public:
    Ptr_to_T(T* p, T* v, int s); // bind to array v of size s, initial value p
    Ptr_to_T(T* p); // bind to single object, initial value p
    Ptr_to_T& operator++(); // prefix
    Ptr_to_T operator++(int); // postfix
    Ptr_to_T& operator--(); // prefix
    Ptr_to_T operator--(int); // postfix
    T&operator*() ; // prefix
}

为什么前缀运算符返回引用,而后缀运算符返回值?
谢谢。

Ptr_to_T& operator--(); // 前缀 Ptr_to_T operator--(int); // 后缀 - David Allan Finch
3个回答

17

后缀运算符返回被增加之前的值的副本,因此它必须返回一个临时对象。前缀运算符返回对象的当前值,因此它可以返回当前值的引用。


结合不能通过引用返回临时对象的事实,这是一个很好的答案。 - xtofl

8
为了更好地理解,你需要想象(或查看)这些运算符是如何实现的。通常,前缀运算符++会写成类似于以下内容:
MyType& operator++()
{
    // do the incrementation
    return *this;
}

由于this已经被“原地”修改,因此我们可以返回对实例的引用,以避免无用的复制。

现在,这是后缀运算符++的代码:

MyType operator++(int)
{
    MyType tmp(*this); // create a copy of 'this'
    ++(*this); // use the prefix operator to perform the increment
    return tmp; // return the temporary
}

作为后缀运算符返回临时值,必须按值返回它(否则,您将获得悬空引用)。 C++ Faq Lite 也有一段关于此主题的内容。

我明白了: CircularInt.cpp:在成员函数“CircularInt& CircularInt::operator++(int)”中: CircularInt.cpp:48:17: 警告:返回对本地变量“result”的引用[-Wreturn-local-addr] CircularInt result(*this); // 为结果制作副本 - Tomer
1
@Tomer:你不能返回一个局部变量的引用,因为当离开函数时该变量将被销毁,所以调用者最终会得到一个不再存在的变量的引用。你需要返回一个值而不是一个引用。 - Luc Touraille

0
假设我使用重载的前置递增来递增一个私有成员。返回对私有成员的引用是否会将++private_var表达式转换为lvalue,从而使直接修改私有成员成为可能?

你返回的不是私有成员的引用,而是你的类对象的引用。(因为外部世界正在增加你的对象,而不是它的私有字段)。 - Kasprzol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接