C中的std :: array等效项

时间:2018-09-01 11:08:00

标签: c arrays vector

我是C和C ++的新手,并且我至少在C ++中读到,在使用向量和数组时,尤其是在将它们传递到函数中时,最好使用std :: array或std :: vector。 / p>

在我的研究中,我发现以下几点很有意义。我想使用std :: vector可以解决在变量范围之外建立索引的问题。

void foo(int arr[10]) { arr[9] = 0; }

void bar() {
    int data[] = {1, 2};
    foo(data);
}
     

上面的代码是错误的,但是编译器认为一切都很好并且   不会发出有关缓冲区溢出的警告。

     

请使用具有一致值的std :: array或std :: vector   语义并缺乏任何会产生诸如以下错误的“特殊”行为   以上。

(来自bames53的答复,谢谢!)

我要编码的是

float foo(int X, int Y, int l){
    // X and Y are arrays of length l
    float z[l];
    for (int i = 0; i < l; i ++){
        z[i] = X[i]+Y[i];
    }
    return z;
}

int bar(){
    int l = 100;
    int X[l];
    int Y[l];
    float z[l];
    z = foo(X,Y,l);
    return 0;
}

我希望将此代码用C编码,所以我的问题是C是否有std :: vector构造?我找不到任何东西。

预先感谢,也请原谅我的编码(我在C和C ++中像草一般)

3 个答案:

答案 0 :(得分:5)

标准C没有像std::vector或其他容器结构那样的东西。您所获得的只是内置数组和malloc

  

我想使用std :: vector可以解决在变量范围之外建立索引的问题。

您可能会这样认为,但是您会错的:在std::vector边界之外建立索引与内置数组一样糟糕。 operator[]的{​​{1}}也不做任何边界检查(或至少不能保证)。如果要检查索引操作,则需要使用std::vector而不是arr.at(i)

还要注意类似的代码

arr[i]

是错误的,因为在C(或C ++)中没有数组值。当您尝试获取数组的值时,实际上会获得指向其第一个元素的指针。但是当函数返回时,第一个元素(以及所有其他元素和整个数组)将被破坏,因此这是一个经典的无用后错误:调用者获得了一个悬空指针,该指针指向不再存在的对象。

惯用的C解决方案是让调用者处理内存分配,并传递函数刚刚写入的输出参数:

float z[l];
...
return z;

也就是说,有一些库为C提供了动态数据结构,但是它们的外观和感觉与C ++和void foo(float *z, const int *X, const int *Y, int l){ // X and Y are arrays of length l for (int i = 0; i < l; i ++){ z[i] = X[i]+Y[i]; } } 有很大不同(例如,我对GLib有所了解)。

答案 1 :(得分:0)

您的问题可能对某些语言的程序员很敏感。 由于不同的语言具有不同的设计决策,因此可以考虑将一种语言的结构转换为另一种语言。

C ++和C占有很大一部分,以某种方式C代码可以(无需大量修改)被编译为C ++。但是,如果您学习精通C ++,您将意识到,由于C的工作原理,会发生很多奇怪的事情。

回到重点:C ++包含一个标准库,其容器为std::vector。这些容器利用了C:中没有的几种C ++结构:

  • RAII(实例超出范围时执行析构函数的事实)将防止分配的内存发生内存泄漏
  • 模板将允许类型安全性不混用double,float,class ...
  • 操作符重载将允许同一功能使用不同的签名(例如擦除)
  • 成员功能

这些都不存在于C中,因此,为了具有相似的结构,需要几种适应才能获得行为几乎相同的数据结构。

根据我的经验,大多数C项目都有自己的通用数据结构版本,通常基于void*。通常,它看起来类似于:

 struct Vector
 {
      void *data;
      long  size;
      long  capacity;
 };

 Vector *CreateVector()
 {
      Vector *v = (Vector *)(malloc(sizeof(Vector)));
      memset(v, 0, sizeof(Vector));
      return v;
 }

 void DestroyVector(Vector *v)
 {
      if (v->data)
      {
          for (long i = 0; i < v->size; ++i)
              free(data[i]);
          free(v->data);
      }
      free(v);
 }

 // ...

或者,您可以混合使用C和C ++。

 struct Vector
 {
      void *cppVector;
 };

 #ifdef __cplusplus
 extern "C" {
 #endif

 Vector CreateVector()
 void DestroyVector(Vector v)

 #ifdef __cplusplus
 }
 #endif

vectorimplementation.cpp

 #include "vector.h"

 struct CDataFree
 {
       void operator(void *ptr) { if (ptr) free(ptr); }
 };
 using CData = std::unique_ptr<void*, CDataFree>;

 Vector CreateVector()
 {
      Vector v;
      v.cppVector = static_cast<void*>(std::make_unique<std::vector<CData>>().release());
      return v;
 }

 void DestroyVector(Vector v)
 {
      auto cppV = static_cast<std::vector<CData>>(v.cppVector);
      auto freeAsUniquePtr = std::unique_ptr<std::vector<CData>>(cppV);
 }

 // ...

答案 2 :(得分:-1)

c中与std::array最接近的等效项可能是预处理器宏定义,例如

#define ARRAY(type,name,length) \
     type name[(length)]