我是初学C++程序员,所以我学会了使用数组而不是向量(这似乎是做事情的一般方法,然后转向向量).
我注意到很多关于SO的答案建议使用向量而不是数组,而字符串则用于char数组.看来这是用C++编写代码的"正确"方法.
总而言之,它何时值得使用经典数组/ char*(如果有的话)?
编写应该在其他项目中使用的代码时,特别是如果您定位可能不存在STL的特殊平台(嵌入式,游戏控制台等).
具有特殊要求的旧项目或项目可能不希望在STL库上引入依赖项.依赖于数组,char*或任何与任何东西兼容的接口,因为它是语言的一部分.但是,并不保证STL存在于所有构建环境中.
决不.
如果一个原始数组似乎比一个向量更好的解决方案(由于其他原因在这里说),那么我在C++ 11编译器(或boost :: array)中使用std :: tr1 :: array或std :: array .它只是进行我将要做的检查以确保并且大小值使用使DRY自动实现(例如,我在循环中使用大小,以便将来更改数组声明将自动工作).
这是数组实现"是"一个带有检查和提供大小常量的原始数组,因此很容易在嵌入式代码中获取数组代码,因为代码对于任何编译器来说都不是"太聪明".至于编译器支持模板,我会在我的代码中复制boost头,以允许我使用这个而不是原始数组.因为使用原始数组显然很容易出错.原始数组是邪恶的.它们容易出错.
它与STL算法(如果可用)配合得很好.
现在,有两种情况需要使用原始数组(义务):当你使用纯C代码时(不与C代码通信,而是在C代码中编写代码,如C库).但那是另一种语言.
另一个原因是编译器根本不支持模板...
这个问题实际上可以分为两部分:
我该如何管理平面阵列数据的内存?
我应该如何访问平面阵列的元素?
我个人更喜欢使用std :: vector来管理内存,除非我需要保持与不使用STL的代码的兼容性(即与直接C代码连接时).使用new或malloc分配的原始数组制作异常安全的代码要困难得多(部分原因是因为它很容易忘记你需要担心它).有关原因,请参阅有关RAII的任何文章.
在实践中,std :: vector实现为平面数组.因此,总是可以拉出原始数组并使用C风格的访问模式.我通常从向量下标运算符语法开始.对于某些编译器,在生成调试版本时,向量提供自动边界检查.这很慢(通常是紧密循环的10倍减速),但有助于找到某些类型的错误.
如果在特定平台上进行性能分析表明operator []是瓶颈,那么我切换到直接访问原始数组.有趣的是,根据编译器和操作系统,使用STL向量有时比原始数组更快.
以下是一个简单的测试应用程序的一些结果.它是使用Visual Studio 2008在32位版本模式下使用/ O2优化编译的,并在Vista x64上运行.使用64位测试应用程序可以获得类似的结果.
Binary search... fill vector (for reference) : 0.27 s array with ptr math : 0.38 s <-- C-style pointers lose array with int index : 0.23 s <-- [] on raw array wins array with ptrdiff_t index : 0.24 s vector with int index : 0.30 s <-- small penalty for vector abstraction vector with ptrdiff_t index : 0.30 s Counting memory (de)allocation... memset (for reference) : 2.85 s fill malloc-ed raw array with [] : 2.66 s fill malloc-ed raw array with ptr : 2.81 s fill new-ed raw array with [] : 2.64 s fill new-ed raw array with ptr : 2.65 s fill vector as array : 3.06 s \ something's slower fill vector : 3.05 s / with vector! NOT counting memory (de)allocation... memset (for reference) : 2.57 s fill malloc-ed raw array with [] : 2.86 s fill malloc-ed raw array with ptr : 2.60 s fill new-ed raw array with [] : 2.63 s fill new-ed raw array with ptr : 2.78 s fill vector as array : 2.49 s \ after discounting the fill vector : 2.54 s / (de)allocation vector is faster!
码:
#define WINDOWS_LEAN_AND_MEAN #include#include #include #include using namespace std; __int64 freq; // initialized in main int const N = 1024*1024*1024/sizeof(int)/2; // 1/2 GB of data int const nIter = 10; class Timer { public: Timer(char *name) : name(name) { QueryPerformanceCounter((LARGE_INTEGER*)&start); } ~Timer() { __int64 stop; QueryPerformanceCounter((LARGE_INTEGER*)&stop); printf(" %36s : % 4.2f s\n", name.c_str(), (stop - start)/double(freq)); } private: string const name; __int64 start; }; template int binarySearch_indexed(Container sortedArray, Index first, Index last, int key) { while (first <= last) { Index mid = (first + last) / 2; // NOT safe if (first+last) is too big! if (key > sortedArray[mid]) first = mid + 1; else if (key < sortedArray[mid]) last = mid - 1; else return mid; } return 0; // Use "(Index)-1" in real code } int Dummy = -1; int const *binarySearch_ptr(int const *first, int const *last, int key) { while (first <= last) { int const *mid = (int const *)(((unsigned __int64)first + (unsigned __int64)last) / 2); if (key > *mid) first = mid + 1; else if (key < *mid) last = mid - 1; else return mid; } return &Dummy; // no NULL checks: don't do this for real } void timeFillWithAlloc() { printf("Counting memory (de)allocation...\n"); { Timer tt("memset (for reference)"); int *data = (int*)malloc(N*sizeof(int)); for (int it=0; it data(N); for (int it=0; it data(N); for (int it=0; it data(N); { Timer tt("fill vector as array"); for (int it=0; it data(N); { Timer tt("fill vector"); for (int it=0; it data(N); { Timer tt("fill vector (for reference)"); for (size_t i=0; i ( &data[0], 0, (int)data.size(), -1)]; } } { Timer tt("array with ptrdiff_t index"); int sum = 0; for (int i=-1000000; i<1000000; i++) { sum += data[binarySearch_indexed ( &data[0], 0, (ptrdiff_t)data.size(), -1)]; } } { Timer tt("vector with int index"); int sum = 0; for (int i=-1000000; i<1000000; i++) { sum += data[binarySearch_indexed const &, int>( data, 0, (int)data.size(), -1)]; } } { Timer tt("vector with ptrdiff_t index"); int sum = 0; for (int i=-1000000; i<1000000; i++) { sum += data[binarySearch_indexed const &, ptrdiff_t>( data, 0, (ptrdiff_t)data.size(), -1)]; } } printf("\n"); } int main(int argc, char **argv) { QueryPerformanceFrequency((LARGE_INTEGER*)&freq); timeBinarySearch(); timeFillWithAlloc(); timeFillNoAlloc(); return 0; }