在我们的c++课程中,他们建议不要再在新项目中使用c++数组。据我所知,Stroustroup本人建议不要使用数组。但是否存在显著的性能差异?


当前回答

如果不需要动态调整大小,则会有存储容量的内存开销(一个指针/size_t)。就是这样。

其他回答

STL is a heavily optimized library. In fact, it's even suggested to use STL in games where high performance might be needed. Arrays are too error prone to be used in day to day tasks. Today's compilers are also very smart and can really produce excellent code with STL. If you know what you are doing, STL can usually provide the necessary performance. For example by initializing vectors to required size (if you know from start), you can basically achieve the array performance. However, there might be cases where you still need arrays. When interfacing with low level code (i.e. assembly) or old libraries that require arrays, you might not be able to use vectors.

下面是简单的测试:

c++数组vs Vector性能测试说明

与“对向量和数组/指针的基本索引、解引用和增量操作生成的汇编代码的比较”的结论相矛盾。

数组和向量之间一定有区别。测试是这么说的…试试吧,代码就在那里……

假设一个固定长度的数组(例如int* v = new int[1000];vs std::vector<int> v(1000);, v的大小保持固定在1000),唯一真正重要的性能考虑因素(或者至少对我来说,当我处于类似的困境时)是访问元素的速度。我查了一下STL的向量代码,下面是我的发现:

const_reference
operator[](size_type __n) const
{ return *(this->_M_impl._M_start + __n); }

这个函数肯定会被编译器内联。所以,只要你计划对v做的唯一一件事就是用operator[]访问它的元素,看起来在性能上不应该有任何差别。

应该避免使用带有new的c++数组(即使用动态数组)。这里有一个问题,你必须跟踪大小,你需要手动删除它们,做各种各样的家务。

在堆栈上使用数组也是不鼓励的,因为您没有范围检查,并且传递数组将丢失关于其大小的任何信息(数组到指针的转换)。在这种情况下,应该使用std::array,它将c++数组包装在一个小类中,并提供一个size函数和迭代器来迭代它。

现在,std::vector vs.原生c++数组(取自互联网):

// Comparison of assembly code generated for basic indexing, dereferencing, 
// and increment operations on vectors and arrays/pointers.

// Assembly code was generated by gcc 4.1.0 invoked with  g++ -O3 -S  on a 
// x86_64-suse-linux machine.

#include <vector>

struct S
{
  int padding;

  std::vector<int> v;
  int * p;
  std::vector<int>::iterator i;
};

int pointer_index (S & s) { return s.p[3]; }
  // movq    32(%rdi), %rax
  // movl    12(%rax), %eax
  // ret

int vector_index (S & s) { return s.v[3]; }
  // movq    8(%rdi), %rax
  // movl    12(%rax), %eax
  // ret

// Conclusion: Indexing a vector is the same damn thing as indexing a pointer.

int pointer_deref (S & s) { return *s.p; }
  // movq    32(%rdi), %rax
  // movl    (%rax), %eax
  // ret

int iterator_deref (S & s) { return *s.i; }
  // movq    40(%rdi), %rax
  // movl    (%rax), %eax
  // ret

// Conclusion: Dereferencing a vector iterator is the same damn thing 
// as dereferencing a pointer.

void pointer_increment (S & s) { ++s.p; }
  // addq    $4, 32(%rdi)
  // ret

void iterator_increment (S & s) { ++s.i; }
  // addq    $4, 40(%rdi)
  // ret

// Conclusion: Incrementing a vector iterator is the same damn thing as 
// incrementing a pointer.

注意:如果你用new分配数组,并分配非类对象(如纯int)或没有用户定义的构造函数的类,并且你不想让你的元素初始化,使用new-allocated数组可以有性能优势,因为std::vector在构造时将所有元素初始化为默认值(例如int为0)(感谢@bernie提醒我)。

对于定长数组,在发布版本中性能是相同的(相对于vector<>),但在调试版本中,根据我的经验,低级数组的优势是20倍(MS Visual Studio 2015, c++ 11)。

因此,如果您(或您的同事)倾向于在数组使用中引入错误,那么支持STL的“节省调试时间”参数可能是有效的,但如果您的调试时间主要用于等待代码运行到您当前正在处理的位置,以便您可以逐步检查它,则可能不是有效的。

处理数字密集型代码的有经验的开发人员有时属于第二组(特别是如果他们使用vector:))。