You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++后置递减运算符重载值传递疑问:返回值为何修改对象?

关于C++后置递减运算符重载的传值问题解答

1. 为什么返回值时对象本身仍会被修改?

不管重载后置--时返回值还是引用,对象本身被修改的核心原因是你在重载函数里已经执行了m_int--——这行代码直接操作了当前对象的成员变量,和返回值的类型毫无关系。返回值只是把修改前的对象副本返回给调用者使用,对象本身的修改在执行m_int--时就已经完成了。

看你代码里的后置--实现:

MyInteger operator--(int) {
    MyInteger myint = *this; // 保存当前对象的副本(修改前的值)
    m_int--; // 这里已经把当前对象的m_int减1,对象本身状态改变
    return myint; // 返回的是修改前的副本,不影响对象本身的修改结果
}

所以只要函数里写了m_int--,对象本身就一定会被修改,返回值只是提供“递减前的原始值”供调用场景使用而已。

2. 返回引用时输出一致是巧合,本质是错误写法

你尝试改成MyInteger& operator--(int),如果沿用原来的逻辑:

MyInteger& operator--(int) {
    MyInteger myint = *this;
    m_int--;
    return myint; // 返回局部对象的引用!
}

这里返回的myint是函数内部的局部变量,函数执行结束后这个局部对象会被销毁,返回的引用就变成了悬垂引用,属于C++未定义行为——这次测试输出一致只是运气好,换个编译器、优化等级或者运行环境,大概率会崩溃或输出乱码。

如果硬要返回引用,只能返回修改后的当前对象,但这完全违背了后置--的语义(后置是先取值再递减,前置是先递减再取值),比如:

MyInteger& operator--(int) {
    m_int--;
    return *this; // 返回修改后的对象
}

此时调用myint--得到的是递减后的值,和前置--效果完全一样,不符合C++原生后置--的设计意图,是错误的重载方式。

3. 为什么后置递减必须返回值而非引用?

C++原生后置--的语义是**“先返回当前值,再对变量执行递减”**,比如:

int a = 5;
cout << a-- << endl; // 输出5,随后a变为4

要实现这个语义,必须返回递减前的对象状态副本——因为递减操作已经修改了当前对象的状态,只能通过保存副本的方式返回原始值。

如果返回引用,要么返回局部对象的引用(悬垂引用,未定义行为),要么返回修改后的当前对象(违背后置--的语义),这两种情况都不符合要求。而前置++/--返回引用是合理的,因为它的语义是先修改对象再返回当前对象,返回引用不存在问题。

另外补充你代码里的一个小优化点:ostream& operator<<的参数MyInteger myint是传值调用,会导致每次输出都拷贝对象,建议改成const MyInteger& myint以避免不必要的拷贝:

ostream& operator<<(ostream& cout, const MyInteger& myint) {
    cout << myint.m_int;
    return cout;
}

内容的提问来源于stack exchange,提问作者Lelly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 15:32:51