简体   繁体   中英

How to pass a dynamically allocated array with “size determined at run time” as a reference?

I know how to pass an array of constant size as a reference, but I want to know that how to pass an array of variable size as a reference to another function. Any help would be much appreciated. Thank you

For example, I have the following code snippet:

void y(int (&arr)[n]) //Gives error
{}

void x(Node * tree, int n)
{
     int arr[n];
     y(arr);
}

I heard that we can templateize the function and make the size a template parameter but I am unable to do so.

Simple: don't. Use std::array or std::vector instead:

int get_max(std::vector<int> & vec) {//Could use const& instead, if it doesn't need to be modified
    int max = std::numeric_limits<int>::min();
    for(int & val : vec) {if(max < val) max = val;
    return max;
}

int get_max(std::array<int, 20> & arr) {//Could use const& instead
    int max = std::numeric_limits<int>::min();
    for(int & val : arr) {if(max < val) max = val;
    return max;
}

If you want this to work for any std::array or any std::vector , you can template them like so:

template<typename T>
T get_max(std::vector<T> const& vec) {
    if(vec.size() == 0) throw std::runtime_error("Vector is empty!");
    T const* max = &vec[0];
    for(T const& val : vec) if(*max < val) max = &val;
    return *max;
}

template<typename T, size_t N>
T get_max(std::array<T, N> const& arr) {
    static_assert(N > 0, "Array is empty!");
    T * max = &arr[0];
    for(T & val : arr) if(*max < val) max = &val;
    return *max;
}

Your code should now look like this to compensate:

void y(std::vector<int> & arr) //Can be const& if you don't need to modify it.
{}

void x(Node * tree, int n)
{
     std::vector<int> arr(n); //Will initialize n elements to all be 0.
     y(arr);
}

Xirema already mentioned how to resolve this using std::vector / std::array .

I don't know your exact case, so will just describe another options, despite the fact, that std::vector / std::array is the best.

Pointers option

Here you have believe, that arr and n arguments of y are consistent. And handle arr size manually.

void y(int * arr, const int n) {}

void x(Node * tree, int n) {
     int arr[n];
     y(arr, n);
}

Templates option

This will work, howether it will instantiate 2 templates on each new N value.

template <size_t N>
void y(int (&arr)[N]) {}

template <size_t N>
void x(Node * tree) {
     int arr[N];
     y<N>(arr);
}

This answer is to illustrate how to work with VLA in C++ when passing it as a function parameter.

In c99, the syntax allows you to pass the size of the array as a parameter to the function, and use the function parameter to declare the size of the VLA:

void y (int n, int (*arr)[n])
{}

void x (int n)
{
    int arr[n];
    y(n, &arr);
}

C++ uses "function name mangling" as a technique to encode the parameter types accepted by the function into the function name to support function overloading. However, in GCC, since VLA is not a C++ supported feature, there is no mangling convention for it. One could argue this is a G++ bug (or incomplete support of the VLA extension), but it is what it is. To mimic the pass by reference, accept the decayed pointer as the parameter, and cast it to a reference to the VLA.

void y(int n, int *x)
{
    int (&arr)[n] = reinterpret_cast<int (&)[n]>(*x);
}

void x(int n)
{
    int arr[n];
    y(n, arr);
}

I have verified this works for GCC 4.8.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM