在C ++中,i ++和++ i之间有性能差异吗?
我们有问题, 在C中 , i++
和++i
之间有性能差异吗?
C ++的答案是什么?
[内容提要:使用++i
,如果你没有特别原因需要使用i++
]
对于C ++来说,答案有点复杂。
如果i
是一个简单类型(不是C ++类的一个实例),那么由于编译器正在生成代码,因此C(“不存在性能差异”)给出的答案成立。
但是,如果i
是一个C ++类的实例,那么i++
和++i
正在调用其中一个operator++
函数。 以下是这些功能的标准配对:
Foo& Foo::operator++() // called for ++i
{
this->data += 1;
return *this;
}
Foo Foo::operator++(int ignored_dummy_value) // called for i++
{
Foo tmp(*this); // variable "tmp" cannot be optimized away by the compiler
++(*this);
return tmp;
}
由于编译器不生成代码,而只是调用operator++
函数,因此无法优化tmp
变量及其关联的拷贝构造函数。 如果拷贝构造函数很昂贵,那么这会对性能产生重大影响。
是。 有。
++运算符可能被定义或不定义为一个函数。 对于原始类型(int,double,...),运算符是内置的,因此编译器可能会优化您的代码。 但是在定义++运算符的对象的情况下,情况是不同的。
运算符++(int)函数必须创建一个副本。 这是因为postfix ++需要返回一个不同于它所保存的值:它必须在temp变量中保存它的值,增加它的值并返回temp。 在operator ++(),前缀++的情况下,不需要创建副本:对象可以自行增加,然后简单地返回它自己。
这里是一个例子:
struct C
{
C& operator++(); // prefix
C operator++(int); // postfix
private:
int i_;
};
C& C::operator++()
{
++i_;
return *this; // self, no copy created
}
C C::operator++(int ignored_dummy_value)
{
C t(*this);
++(*this);
return t; // return a copy
}
每次调用operator ++(int)时,都必须创建一个副本,编译器无法对此做任何事情。 当给出选择时,使用operator ++(); 这样你就不会保存副本。 在许多增量(大循环?)和/或大对象的情况下,它可能很重要。
以下是递增运算符处于不同翻译单位时的基准。 用g ++ 4.5编译。
现在忽略样式问题
// a.cc
#include <ctime>
#include <array>
class Something {
public:
Something& operator++();
Something operator++(int);
private:
std::array<int,PACKET_SIZE> data;
};
int main () {
Something s;
for (int i=0; i<1024*1024*30; ++i) ++s; // warm up
std::clock_t a = clock();
for (int i=0; i<1024*1024*30; ++i) ++s;
a = clock() - a;
for (int i=0; i<1024*1024*30; ++i) s++; // warm up
std::clock_t b = clock();
for (int i=0; i<1024*1024*30; ++i) s++;
b = clock() - b;
std::cout << "a=" << (a/double(CLOCKS_PER_SEC))
<< ", b=" << (b/double(CLOCKS_PER_SEC)) << 'n';
return 0;
}
O(n)增量
测试
// b.cc
#include <array>
class Something {
public:
Something& operator++();
Something operator++(int);
private:
std::array<int,PACKET_SIZE> data;
};
Something& Something::operator++()
{
for (auto it=data.begin(), end=data.end(); it!=end; ++it)
++*it;
return *this;
}
Something Something::operator++(int)
{
Something ret = *this;
++*this;
return ret;
}
结果
在虚拟机上使用g ++ 4.5的结果(时间以秒为单位):
Flags (--std=c++0x) ++i i++
-DPACKET_SIZE=50 -O1 1.70 2.39
-DPACKET_SIZE=50 -O3 0.59 1.00
-DPACKET_SIZE=500 -O1 10.51 13.28
-DPACKET_SIZE=500 -O3 4.28 6.82
O(1)增量
测试
现在让我们看看以下文件:
// c.cc
#include <array>
class Something {
public:
Something& operator++();
Something operator++(int);
private:
std::array<int,PACKET_SIZE> data;
};
Something& Something::operator++()
{
return *this;
}
Something Something::operator++(int)
{
Something ret = *this;
++*this;
return ret;
}
它在增量中没有做任何事情。 这模拟了增量具有不变复杂性的情况。
结果
结果现在变化极大:
Flags (--std=c++0x) ++i i++
-DPACKET_SIZE=50 -O1 0.05 0.74
-DPACKET_SIZE=50 -O3 0.08 0.97
-DPACKET_SIZE=500 -O1 0.05 2.79
-DPACKET_SIZE=500 -O3 0.08 2.18
-DPACKET_SIZE=5000 -O3 0.07 21.90
结论
性能方面
如果你不需要以前的值,那就习惯使用预增值。 即使与内置类型保持一致,您也会习惯它,并且如果您使用自定义类型替换内置类型,则不会冒着遭受不必要性能损失的风险。
语义明智
i++
说increment i, I am interested in the previous value, though
。 ++i
说increment i, I am interested in the current value
或increment i, no interest in the previous value
。 再一次,即使你现在不适应,你也会习惯它。 克努特。
不成熟的优化是万恶之源。 由于过早的悲观化。
链接地址: http://www.djcxy.com/p/72251.html上一篇: Is there a performance difference between i++ and ++i in C++?
下一篇: c++