Search code examples
c++arraysc++11initializer-listdefault-arguments

Fixed-size and zero-initialised array as a default argument in C++11


Context: I thought that the following SSCCE, compiled with compile: g++ -std=c++11 main.cpp, would zero-initialise a fixed-size array arr:

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

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

However, I debugged with gdb and found out that arr = 0x0 (null). I (wildly) guess this is because int arr[4] is very much like int* arr but additionally telling the compiler to only allow arrays of length 4. Hence, what actually happens is int arr* = {0} ie I am just using an initializer-list to zero-initialize a pointer.

I know I can circumvent this problem by reverting back to using overloads instead of default arguments:

void foo(int arr[4]) { }

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

This does give me a zero-initialized fixed-size array in foo, as expected. However, I think it would be nice to merge these two overloaded functions into one by using some default argument, similarly to the SSCCE.

Question: Is zero-initialisation of a default argument fixed-size array possible in C++11. If so, how?


Solution

  • The main problem you are encountering is that void foo(int arr[4]) decays to void foo(int* arr), so your function does actually accept a pointer instead of an array. The simple proof is that foo(nullptr); will compile without errors or warnings.

    As such the declaration void foo(int arr[4] = {0}); is actually void foo(int* arr = {0}); which initializes the pointer to 0 (trying to change {0} to any other number will actually cause a compile time error).

    The best alternative is most likely to use std::array instead, for example:

    #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;  
    }
    

    Note that currently there is no convenient way to convert "raw" C-style arrays to std::array, though there is a helper function in experimental/array called std::to_array which may be merged into the standard in a future version