既然我们有std :: array,那么C-style数组的用途是什么?

时间:2011-05-24 13:58:01

标签: c++ arrays c++11 initialization

std::array远远优于C阵列。即使我想与遗留代码进行互操作,我也可以使用std::array::data()。我有什么理由想要一个老派阵列吗?

7 个答案:

答案 0 :(得分:59)

除非我错过了某些内容(我没有过多地关注标准中最新的更改),否则C样式数组的大部分用法仍然存在。 std::array允许静态初始化,但它仍然不会为您计算初​​始值设定项。并且因为在std::array之前唯一真正使用C样式数组的是静态初始化表 沿着这条线:

MyStruct const table[] =
{
    { something1, otherthing1 },
    //  ...
};

使用通常的beginend模板函数(在 C ++ 11)迭代它们。没有提到编译器根据初始化器的数量确定的大小。

编辑:我忘了另一件事:字符串文字仍然是C样式数组;即类型char[]。我不认为有人会因为我们有std::array而排除使用字符串文字。

答案 1 :(得分:29)

没有。呃,直言不讳地说。并且有30个字符。

当然,您需要C数组来实现std::array,但这并不是用户想要C数组的真正原因。另外,不,std::array的性能不低于C数组,具有边界检查访问权限的选项。最后,任何C ++程序都依赖于标准库是完全合理的 - 这就是它的标准 - 如果你没有访问标准库,那么你的编译器是不符合标准的问题被标记为“C ++”,而不是“C ++和那些非C ++的东西错过了一半的规范,因为他们感觉不合适。”。

答案 2 :(得分:25)

使用C维数组比使用多维数组更容易std::array。例如,

char c_arr[5][6][7];

而不是

std::array<std::array<std::array<char, 7>, 6>, 5> cpp_arr;

同样由于C数组的自动衰减属性,上面示例中的c_arr[i]将衰减为指针,您只需要将剩余的维度作为另外两个参数传递。我的观点是c_arr复制并不昂贵。但是,cpp_arr[i]复制成本非常高。

答案 3 :(得分:13)

正如Sumant所说,内置C阵列比使用std::array更容易使用多维数组。

嵌套时,std::array会变得非常难以阅读并且不必要地冗长。

例如:

std::array<std::array<int, 3>, 3> arr1; 

相比
char c_arr[3][3]; 

另请注意,begin()end()size()在嵌套std::array时都会返回无意义的值。

由于这些原因,我创建了自己的固定大小的多维数组容器array_2darray_3d。它们类似于std::array,但适用于2维和3维的多维数组。它们比内置的多维数组更安全,性能更差。我没有包含尺寸大于3的多维数组的容器,因为它们并不常见。在C ++ 0x中,可以制作支持任意数量维度的可变参数模板版本。

二维变体的一个例子:

//Create an array 3 x 5 (Notice the extra pair of braces) 

fsma::array_2d <double, 3, 5> my2darr = {{
    { 32.19, 47.29, 31.99, 19.11, 11.19},
    { 11.29, 22.49, 33.47, 17.29, 5.01 },
    { 41.97, 22.09, 9.76, 22.55, 6.22 }
}};

此处提供完整文档:

http://fsma.googlecode.com/files/fsma.html

您可以在此处下载图书馆:

http://fsma.googlecode.com/files/fsma.zip

答案 4 :(得分:5)

C ++中可用的C风格数组实际上比真正的C数组要少得多。不同的是,在C中,数组类型可以具有运行时大小。以下是有效的C代码,但既不能用C ++ C风格的数组表示,也不能用C ++ array<>类型表示:

void foo(int bar) {
    double tempArray[bar];
    //Do something with the bar elements in tempArray.
}

在C ++中,您必须在堆上分配临时数组:

void foo(int bar) {
    double* tempArray = new double[bar];
    //Do something with the bar elements behind tempArray.
    delete[] tempArray;
}

使用std::array<>无法实现这一点,因为bar在编译时是未知的,它需要在C ++或std::vector<>中使用C样式数组。


虽然第一个示例可以相对容易地用C ++表示(虽然需要new[]delete[]),但如果没有std::vector<>,则无法在C ++中实现以下内容:

void smoothImage(int width, int height, int (*pixels)[width]) {
    int (*copy)[width] = malloc(height*sizeof(*copy));
    memcpy(copy, pixels, height*sizeof(*copy));
    for(y = height; y--; ) {
        for(x = width; x--; ) {
            pixels[y][x] = //compute smoothed value based on data around copy[y][x]
        }
    }
    free(copy);
}

关键是,指向行数组int (*)[width]的指针不能在C ++中使用运行时宽度,这使得C ++中的任何图像处理代码都比在C中复杂得多。典型的C ++实现图像处理示例如下所示:

void smoothImage(int width, int height, int* pixels) {
    int* copy = new int[height*width];
    memcpy(copy, pixels, height*width*sizeof(*copy));
    for(y = height; y--; ) {
        for(x = width; x--; ) {
            pixels[y*width + x] = //compute smoothed value based on data around copy[y*width + x]
        }
    }
    delete[] copy;
}

此代码与上面的C代码完全相同,但它需要在使用索引的地方手动执行索引计算。对于2D情况,这仍然是可行的(即使它有很多机会使索引计算错误)。然而,在3D情况下,它变得非常讨厌。

我喜欢用C ++编写代码。但每当我需要操作多维数据时,我真的会问自己是否应该将代码的这一部分移到C中。

答案 5 :(得分:-1)

可能是std::array并不慢。但我使用简单的存储进行了一些基准测试,并从std :: array中读取; 请参阅以下基准测试结果(在W8.1,VS2013 Update 4上):

ARR_SIZE: 100 * 1000
Avrg = Tick / ARR_SIZE;

test_arr_without_init
==>VMem: 5.15Mb
==>PMem: 8.94Mb
==>Tick: 3132
==>Avrg: 0.03132
test_arr_with_init_array_at
==>VMem: 5.16Mb
==>PMem: 8.98Mb
==>Tick: 925
==>Avrg: 0.00925
test_arr_with_array_at
==>VMem: 5.16Mb
==>PMem: 8.97Mb
==>Tick: 769
==>Avrg: 0.00769
test_c_arr_without_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 358
==>Avrg: 0.00358
test_c_arr_with_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 305
==>Avrg: 0.00305

根据否定标记,我使用的代码位于pastebin(link

基准类代码为 here ;

我对基准测试知之甚少......我的代码可能存在缺陷

答案 6 :(得分:-6)

  1. 实现std::array
  2. 之类的内容
  3. 如果您不想使用STL或不能
  4. 表现