当前位置:  开发笔记 > 编程语言 > 正文

你什么时候使用数组而不是矢量/字符串?

如何解决《你什么时候使用数组而不是矢量/字符串?》经验,为你挑选了3个好方法。

我是初学C++程序员,所以我学会了使用数组而不是向量(这似乎是做事情的一般方法,然后转向向量).

我注意到很多关于SO的答案建议使用向量而不是数组,而字符串则用于char数组.看来这是用C++编写代码的"正确"方法.

总而言之,它何时值得使用经典数组/ char*(如果有的话)?



1> Laserallan..:

编写应该在其他项目中使用的代码时,特别是如果您定位可能不存在STL的特殊平台(嵌入式,游戏控制台等).

具有特殊要求的旧项目或项目可能不希望在STL库上引入依赖项.依赖于数组,char*或任何与任何东西兼容的接口,因为它是语言的一部分.但是,并不保证STL存在于所有构建环境中.



2> Klaim..:

决不.

如果一个原始数组似乎比一个向量更好的解决方案(由于其他原因在这里说),那么我在C++ 11编译器(或boost :: array)中使用std :: tr1 :: array或std :: array .它只是进行我将要做的检查以确保并且大小值使用使DRY自动实现(例如,我在循环中使用大小,以便将来更改数组声明将自动工作).

这是数组实现"是"一个带有检查和提供大小常量的原始数组,因此很容易在嵌入式代码中获取数组代码,因为代码对于任何编译器来说都不是"太聪明".至于编译器支持模板,我会在我的代码中复制boost头,以允许我使用这个而不是原始数组.因为使用原始数组显然很容易出错.原始数组是邪恶的.它们容易出错.

它与STL算法(如果可用)配合得很好.

现在,有两种情况需要使用原始数组(义务):当你使用纯C代码时(不与C代码通信,而是在C代码中编写代码,如C库).但那是另一种语言.

另一个原因是编译器根本不支持模板...



3> Mr Fooz..:

这个问题实际上可以分为两部分:

    我该如何管理平面阵列数据的内存?

    我应该如何访问平面阵列的元素?

我个人更喜欢使用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;
}

推荐阅读
mobiledu2402851203
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有