STL的迭代器,前置++什么比后置++要快?
内置类型的前置++和后置++
int a = 0;
int b = a++; //此时b=0,a=1
int c = 0;
int d = ++c; // 此时d = 1, c = 1
换言之,前置++和后置++的区别仅在于++运算符的返回值是自加过后的结果或者是自加之前的副本
在类中重载它们
class Age
{
public:
Age& operator++() //前置++
{
++i;
return *this;
}
const Age operator++(int) //后置++
{
Age tmp = *this;
++(*this); //利用前置++
return tmp;
}
Age& operator=(int i) //赋值操作
{
this->i = i;
return *this;
}
private:
int i;
};
可以看出,如果只是单纯的为了把私有变量i加一,后置++要使用一个tmp在函数栈上保存自加之前的类的副本,会造成额外的内存开销,没有必要,除非遇到了要保存自加前副本的需求。
在STL中的迭代器自加
vector<int> vi{1,2,3};
for (auto iter = vi.begin(); iter != vi.end(); iter++);
for (auto iter = vi.begin(); iter != vi.end(); ++iter);
这样的迭代中,使用++运算符,只是为了让迭代器内置的指针加一而已,并不需要指针移动之前迭代器的副本,所以使用前置++会比后置++更加节省内存,BTW,经测试,在VS2019的环境下,后置++编译器还真没办法优化。
关于重载运算符的返回值(2020/02/29更新)
今天有小伙伴提到,将后置或者前置的重载操作符的函数的返回值设为void也能顺利通过编译并且实现部分功能。但是经过试验,如果前置或者后置的重载操作符的返回值是void,那么编译以下代码就会报错:
class MyInt
{
public:
MyInt() : i(0){}
MyInt& operator++()
{
i = i + 1;
return *this;
}
void operator++(int i)
{
i = i + 1;
}
private:
int i;
};
int main()
{
MyInt i1, i2;
i1 = ++i2; // OK
i2++; // OK
i1 = i2++; // Compile Error!
return 0;
}