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


当前回答

当你想要一个未初始化的缓冲区(例如用作memcpy()的目标)时,使用std::vector与使用raw数组肯定会有性能影响。vector将使用默认构造函数初始化其所有元素。原始数组则不会。

c++规范中std:vector构造函数接受count参数(这是第三种形式):

从各种数据源构造一个新容器,可选地使用用户提供的分配器alloc。

使用默认插入的t的count个实例构造容器。

复杂性

2-3)计数线性

原始数组不会产生这种初始化代价。

注意,使用自定义分配器,可以避免vector元素的“初始化”(即使用默认初始化而不是值初始化)。请看这些问题了解更多细节:

这是c++ 11和Boost下vector::resize(size_type n)的行为吗?容器正确吗? 如何避免std::vector<>来初始化它的所有元素?

其他回答

如果在调试模式下编译软件,许多编译器将不会内联vector的访问器函数。这将使stl向量的实现在性能有问题的情况下变得更慢。它还将使代码更容易调试,因为您可以在调试器中看到分配了多少内存。

在优化模式下,我希望stl向量接近数组的效率。这是因为许多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[]访问它的元素,看起来在性能上不应该有任何差别。

选择STL。没有性能损失。这些算法非常高效,它们在处理我们大多数人不会想到的细节方面做得很好。

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++ 11中使用普通数组的理由就更少了。

从最快到最慢,本质上有3种类型的数组,这取决于它们所具有的特性(当然,实现的质量可以使事情变得非常快,即使是列表中的情况3):

静态的,在编译时大小已知。——std::array<T, N> 动态的,运行时大小已知,从不调整大小。这里的典型优化是,如果数组可以直接分配到堆栈中。——不可用。也许在c++ 14之后,在c++ TS中使用dynarray。在C中有vla 动态的,可在运行时调整大小。——std::向量T > <

为1。常量静态数组,在c++ 11中使用std::array<T, N>。

为2。在运行时指定固定大小的数组,但这不会改变它们的大小,在c++ 14中有讨论,但它已经转移到技术规范,最终由c++ 14制成。

为3。std::vector<T>通常会在堆中请求内存。这可能会影响性能,不过可以使用std::vector<T, MyAlloc<T>>来使用自定义分配器改善这种情况。相对于T mytype[] = new mytype[n];你可以调整它的大小它不会像普通数组那样衰减为指针。

使用上面提到的标准库类型来避免数组退化为指针。如果使用相同的特性集,将节省调试时间,并且性能与普通数组完全相同。