固定大小和零启动数组作为C 11中的默认参数



上下文:我以为以compile: g++ -std=c++11 main.cpp编译的以下SSCCE将零启用固定尺寸的数组arr

void foo(int arr[4] = {0}) { }
int main(int argc, char const *argv[]) {
    foo();
    return 0;
}

但是,我对gdb进行了调试,发现arr = 0x0(null(。我(疯狂地(猜想这是因为int arr[4]非常像int* arr,但还告诉编译器仅允许长度为4. 4.因此,实际上发生的是int arr* = {0},即我只是使用初始化列表来零定位,使指针零化。

我知道我可以通过恢复使用过载而不是默认参数来解决这个问题:

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

这确实使我在foo中的零定位固定尺寸数组,如预期。但是,我认为通过使用一些默认参数将这两个超载函数合并为一个,类似于SSCCE。

问题:默认参数固定大小数组在C 11中可能是零键化。如果是这样,如何?

您遇到的主要问题是 void foo(int arr[4])腐烂到 void foo(int* arr),因此您的功能实际上确实接受指针而不是数组。简单的证据是foo(nullptr);将不带错误或警告编译。

因此,声明void foo(int arr[4] = {0});实际上是void foo(int* arr = {0});,它初始化指针为0(尝试将{0}更改为任何其他数字实际上会导致编译时间错误(。

最好的替代方法最有可能使用std::array,例如:

#include <array>
void foo(std::array<int, 4> arr = {0}) { }
int main(int argc, char const *argv[]) {
    foo();
    // call with an array
    foo({1,2,3,4});
    // providing more values will cause a compile time error
    // foo({2,3,4,5,6,7,8});
    return 0;  
}

请注意,当前没有方便的方法可以将" RAW" C风格数组转换为STD ::数组,尽管experimental/array中有一个辅助功能,称为std::to_array,可以将其合并为未来版本中的标准

最新更新