重载中operator++ () 与operator++(int)的区别

在进行侯捷老师的STL源码阅读时碰到了重载函数operator++() 与operator++(int) ,这让我产生比较大的困惑,为什么operator++(int)需要站位参数,有什么区别么?
刚开始由于无法区分++与–的前缀调用与后缀调用一直被人诟病,最后C++语言得到了扩展,允许重载++与–;

然而语法上确有一个问题,重载函数的区别在于他们参数类型的差异。但不论++与–的前缀和后缀都只有一个参数,C++规定后缀调用需要有一个int型参数作为区分前缀与后缀调用的区别

class ListNode {
public:
	ListNode& operator++();

	const ListNode operator++(int);

	ListNode& operator--();

	const ListNode operator--(int);
	ListNode& operator+=(int);
};

void test()
{
	ListNode test;

	test++; //其实就是调用operator++(0);

	++test; //其实就是调用operator++();

	--test; //其实就是调用operator--();

	test--; //其实就是调用operator--(int);
}

其中要注意的是后缀返回一个const类型,与前缀不同。

我们都知道前缀叫做增加后取回,后缀是取回后增加
所以在使用后缀的时候需要进行const进行限制,这样也符合规范;

ListNode& ListNode::operator++()
{
	*this += 1; //增加

	return *this;//返回值
}

const ListNode ListNode::operator++(int)
{
	ListNode tmp = *this;//取值

	++(*this); //增加

	return tmp; //返回被取回的值
}

后缀的参数并没有使用只是用来区分与前缀的区别调用,后缀必须返回一个对象(增加前的值),假设没有const对象

ListNode i;

i++++; 进行两次增加操作

其实上面的写法等于这种

i.operator++(0).operator++(0);

很明显第一个operator++调用了第二个operator++函数。

有两个理由导致我们应该厌恶上述这种做法,第一是与内置类型行为不一致。当设计一个类遇到问题时,一个好的准则是使该类的行为与int类型一致。而int类型不允许连续进行两次后缀++:

int i;
i++++; // 错误!

第二个原因是使用两次后缀increment所产生的结果与调用者期望的不一致。如上所示,第二次调用operator++改变的值是第一次调用返回对象的值,而不是原始对象的值。因此如果:

i++++;

是合法的,i将仅仅增加了一次。这与人的直觉相违背,使人迷惑(对于int类型和ListNode都是一样),所以最好禁止这么做。

C++禁止int类型这么做,同时你也必须禁止你自己写的类有这样的行为。最容易的方法是让后缀increment 返回const对象。当编译器遇到这样的代码:

i++++; // same as i.operator++(0).operator++(0);

这这种情况下没第一个operator++函数返回了一个const对象,接着又调用了operator++,然而这个函数是一个non-const成员函数,所以不能调用这个函数。

如果你很关心效率问题,当你第一次看到后缀++函数时, 你可能觉得有些问题。这个函数必须建立一个临时对象以做为它的返回值,(参见条款19),上述实现代码建立了一个显示的临时对象(test),这个临时对象必须被构造并在最后被结构。前缀++函数没有这样的临时对象。由此得出一个令人惊讶的结论,如果仅为了提高代码效率,UPInt的调用者应该尽量使用前缀++,少用后缀++,除非确实需要使用后缀++。让我们明确一下,当处理用户定义的类型时,尽可能地使用前缀++,因为它的效率较高。

我们再观察一下后缀与前缀++操作符。它们除了返回值不同外,所完成的功能是一样的,即值加一。简而言之,它们被认为功能一样。那么你如何确保后缀++和前缀++的行为一致呢?当不同的程序员去维护和升级代码时,有什么能保证它们不会产生差异?除非你遵守上述代码里的原则,这才能得到确保。这个原则是后缀++和–应该根据它们的前缀形式来实现。你仅仅需要维护前缀版本,因为后缀形式自动与前缀形式的行为一致。

本文借鉴与引用作者[https://blog.csdn.net/cjluxuwei/article/details/41810867?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-1&spm=1001.2101.3001.4242]

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值