C++中前缀与后缀自增运算符重载的技术疑问
Rational类自增运算符重载常见问题解答
const Rational & Rational::operator++() //Prefix form { numer += denom; return *this; } Rational Rational::operator++(int) //Postfix form { Rational tmp = *this; numer += denom; return tmp; }
上述代码实现了Rational有理数类的前缀与后缀自增运算符(++)重载,类包含私有成员numer(分子)和denom(分母),运算符作用是将Rational对象表示的有理数加1。针对相关技术问题解答如下:
问题1:前缀自增方法的返回类型为const Rational&,但返回语句为*this,这是否实际返回对象而非引用?
不是。*this本身就是当前对象的左值引用,返回类型声明为const Rational&时,直接返回的是当前对象的常量引用,不会触发对象拷贝。只有当返回类型是值类型Rational时,*this才会被拷贝成临时对象返回,这里完全符合引用返回的语义。问题2:书中提及用匿名int参数区分前缀与后缀形式的签名,但两者返回类型也不同,原因是什么?
这是为了对齐C++原生自增运算符的行为:- 原生前缀
++x返回自增后的对象引用,支持链式操作(比如++++x); - 原生后缀
x++返回自增前的临时对象,不支持链式操作(比如x++++会编译报错)。
重载时遵循这个语义是为了符合开发者的使用习惯,保证自定义类型和内置类型的行为一致。另外要注意,C++的函数重载不依赖返回类型,匿名int参数才是编译器区分前后缀版本的核心标识,返回类型不同是语义设计的结果,不是重载的判断依据。
- 原生前缀
问题3:仅通过代码如何判断编译器会选择前缀还是后缀版本的方法?
看调用代码的写法即可:- 如果是
++obj(++放在对象前面),编译器会匹配无参数的operator++(),也就是前缀版本; - 如果是
obj++(++放在对象后面),编译器会匹配带匿名int参数的operator++(int),也就是后缀版本。
另外可以通过链式调用验证:++(++obj)合法(前缀返回引用,可继续自增),而(obj++)++会编译失败(后缀返回临时对象,无法作为左值进行自增),也能反向判断调用的版本。
- 如果是
内容的提问来源于stack exchange,提问作者Afronaut
相关产品推荐
相关产品推荐

