C ++枚举使用比整数慢吗?

这真的是一个简单的问题:

我正在编程一个Go程序。 我应该用QVector<int>还是QVector<Player>代表董事会

 enum Player { EMPTY = 0, BLACK = 1, WHITE = 2 }; 

我想当然,使用Player而不是整数将会变慢。 但我不知道多less,因为我相信使用enum是更好的编码。

我已经做了一些关于分配和比较玩家的testing(而不是int

 QVector<int> vec; vec.resize(10000000); int size = vec.size(); for(int i =0; i<size; ++i) { vec[i] = 0; } for(int i =0; i<size; ++i) { bool b = (vec[i] == 1); } QVector<Player> vec2; vec2.resize(10000000); int size = vec2.size(); for(int i =0; i<size; ++i) { vec2[i] = EMPTY; } for(int i =0; i<size; ++i) { bool b = (vec2[i] == BLACK); } 

基本上只有10%的慢。 继续之前还有什么我应该知道的吗?

谢谢!

编辑:10%的差异并不是我的想象力,它似乎是特定于Qt和QVector。 当我使用std :: vector时,速度是一样的

枚举在编译时被彻底解决(枚举常量为整数文字,枚举variables为整数variables),使用它们没有速度损失。

一般来说,平均枚举不会有一个大于int的基础types(除非你input非常大的常量)。 事实上,在§7.2¶5中明确地说:

枚举的基本types是一个整型,可以表示枚举中定义的所有枚举值。 它是实现定义的,其中整型被用作枚举的基础types, 除非基础types不应该大于int 除非枚举器的值不能放在intunsigned int

你应该在合适的时候使用枚举,因为它们通常会使代码更容易阅读和维护(你曾经试过debugging过一个充满“魔法数字”的程序? :S )。

至于你的结果:可能你的testing方法没有考虑到当你在“普通”机器上运行代码时得到的正常速度波动。 你有没有试过运行多次(100+)次的testing,并计算你的时间的平均和标准偏差? 结果应该是一致的:平均值之间的差值不应该大于两个标准偏差的RSS 2的1或2倍(假设像往常一样,波动的高斯分布)。

你可以做的另一个检查是比较生成的汇编代码(用g ++,你可以用-S开关得到它)。


  1. 在“正常”的个人电脑,你有一些不确定的波动,因为其他任务运行,caching/内存/虚拟机状态,…
  2. Root Sum Squared(平方和平方),平方标准偏差总和的平方根。

一般来说,使用枚举应该使性能完全没有区别。 你是怎么testing这个的?

我只是自己testing。 差异是纯粹的噪音。

刚才我把这两个版本编译成汇编器。 以下是各自的主要function:

INT

 LFB1778: pushl %ebp LCFI11: movl %esp, %ebp LCFI12: subl $8, %esp LCFI13: movl $65535, %edx movl $1, %eax call __Z41__static_initialization_and_destruction_0ii leave ret 

播放机

 LFB1774: pushl %ebp LCFI10: movl %esp, %ebp LCFI11: subl $8, %esp LCFI12: movl $65535, %edx movl $1, %eax call __Z41__static_initialization_and_destruction_0ii leave ret 

基于任何关于微基准性能的陈述是危险的。 有太多的外部因素歪曲数据。

枚举应该不会变慢。 他们被实现为整数。

如果你使用Visual Studio例如你可以创build一个简单的项目,你有

  a=Player::EMPTY; 

如果你右键点击“去反汇编”的代码将是

 mov dword ptr [a],0 

所以编译器replace枚举的值,通常它不会产生任何开销。

那么,我做了一些testing,整数和枚举forms之间没有太大的区别。 我还添加了一个字符forms,一直约6%更快(这是不足为奇,因为它使用较less的内存)。 然后我只用了一个char数组而不是一个vector,这个速度快了300%! 由于我们没有得到什么QVector,它可能是一个数组的包装,而不是我用过的std :: vector。

下面是我使用的代码,使用Dev Studio 2005中的标准版本选项进行编译。请注意,我已经将定时循环更改了一小段时间,因为问题中的代码可以优化为无(您必须检查汇编代码) 。

 #include <windows.h> #include <vector> #include <iostream> using namespace std; enum Player { EMPTY = 0, BLACK = 1, WHITE = 2 }; template <class T, T search> LONGLONG TimeFunction () { vector <T> vec; vec.resize (10000000); size_t size = vec.size (); for (size_t i = 0 ; i < size ; ++i) { vec [i] = static_cast <T> (rand () % 3); } LARGE_INTEGER start, end; QueryPerformanceCounter (&start); for (size_t i = 0 ; i < size ; ++i) { if (vec [i] == search) { break; } } QueryPerformanceCounter (&end); return end.QuadPart - start.QuadPart; } LONGLONG TimeArrayFunction () { size_t size = 10000000; char *vec = new char [size]; for (size_t i = 0 ; i < size ; ++i) { vec [i] = static_cast <char> (rand () % 3); } LARGE_INTEGER start, end; QueryPerformanceCounter (&start); for (size_t i = 0 ; i < size ; ++i) { if (vec [i] == 10) { break; } } QueryPerformanceCounter (&end); delete [] vec; return end.QuadPart - start.QuadPart; } int main () { cout << " Char form = " << TimeFunction <char, 10> () << endl; cout << "Integer form = " << TimeFunction <int, 10> () << endl; cout << " Player form = " << TimeFunction <Player, static_cast <Player> (10)> () << endl; cout << " Array form = " << TimeArrayFunction () << endl; } 

编译器应该将enum转换成整数。 他们在编译时被内联,所以一旦你的程序被编译了,它应该和你自己使用整数一样。

如果你的testing产生不同的结果,testing本身可能会有一些事情发生。 不pipe是那个,还是你的编译器都performance得很奇怪。

这是依赖于实现的,enums和ints很可能具有不同的性能以及相同或不同的汇编代码,虽然这可能是编译器不理想的标志。 一些获得差异的方法是:

  • QVector可能会专门针对你的枚举types做一些令人惊讶的事情。
  • 枚举不会被编译为int,而是“一些整型不大于int”。 int的QVector可能与some_integral_type的QVector有所不同。
  • 即使QVector没有被专门化,编译器也可能比alignmentsome_integral_type更好地alignment内存中的整数,从而在循环遍历枚举或some_integral_type向量时导致更高的caching缺失率。