固定大小和零初始化数组作为 C++11 中的默认参数

Fixed-size and zero-initialised array as a default argument in 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 的数组。因此,实际发生的是 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::array,尽管 experimental/array 中有一个名为 std::to_array 的辅助函数可能会在未来的版本中合并到标准中