在我们的c++课程中,他们建议不要再在新项目中使用c++数组。据我所知,Stroustroup本人建议不要使用数组。但是否存在显著的性能差异?
当前回答
应该避免使用带有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提醒我)。
其他回答
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.
当你想要一个未初始化的缓冲区(例如用作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<>来初始化它的所有元素?
如果不需要动态调整大小,则会有存储容量的内存开销(一个指针/size_t)。就是这样。
为了回应Mehrdad说过的话:
然而,在某些情况下 你仍然需要数组。当 与低级代码(例如: 程序集)或旧的库 需要数组,您可能无法 用向量。
完全不是这样的。向量可以很好地降级为数组/指针,如果你使用:
vector<double> vector;
vector.push_back(42);
double *array = &(*vector.begin());
// pass the array to whatever low-level code you have
这适用于所有主要的STL实现。在下一个标准中,它将被要求工作(即使它现在做得很好)。
对于定长数组,在发布版本中性能是相同的(相对于vector<>),但在调试版本中,根据我的经验,低级数组的优势是20倍(MS Visual Studio 2015, c++ 11)。
因此,如果您(或您的同事)倾向于在数组使用中引入错误,那么支持STL的“节省调试时间”参数可能是有效的,但如果您的调试时间主要用于等待代码运行到您当前正在处理的位置,以便您可以逐步检查它,则可能不是有效的。
处理数字密集型代码的有经验的开发人员有时属于第二组(特别是如果他们使用vector:))。
推荐文章
- 如何构建和使用谷歌TensorFlow c++ api
- 在JavaScript中根据键值查找和删除数组中的对象
- 如何确定一个数组是否包含另一个数组的所有元素
- 给定一个数字数组,返回所有其他数字的乘积的数组(不除法)
- 多维数组如何在内存中格式化?
- 断言是邪恶的吗?
- 下面这些短语在c++中是什么意思:0 -,default-和value-initialization?
- 在STL地图中,使用map::insert比[]更好吗?
- C++ Linux的想法?
- TypeScript枚举对象数组
- 如何为Fedora安装g++ ?
- 获取数组值的键名
- Std::cin输入空格?
- c++标准是否要求iostreams的性能很差,或者我只是在处理一个糟糕的实现?
- 如何规范化一个NumPy数组到一定的范围内?