passing an array as a const argument of a method in C++
Asked Answered
N

5

15

I would like to be able to pass a const array argument to a method in C++.

I know that when you pass an array to method it is the same than passing a pointer to the first item of the array so an easy way is to use the pointer.

void myMethod(int * const inTab)

But having an array is sometimes better, you can write the size of the array for instance.

Nicholenicholl answered 18/7, 2012 at 14:25 Comment(5)
https://mcmap.net/q/821988/-passing-typedef-fixed-sized-array-by-valueHannie
You want to pass a reference to the array. See this question and its answers for a discussion about it.Psyche
Why not use std::vector? parashift.com/c++-faq/arrays-are-evil.htmlTranspicuous
@avasopht: Because arrays aren't always evil, and dynamic allocation sometimes is evil.Charlesettacharleston
Yes, very true. Of course it is important to ensure Kevin and others viewing this question are privy to c++-faq, and some of the dangers associated with the use of arrays. If they run into trouble with std::vector, at least it won't likely be a buffer overrun ;) And also they can start thinking about elegant solutions that sit in the middle, neither allocating nor directly accessing an array.Transpicuous
J
27

You can use a template taking the array size: http://ideone.com/0Qhra

template <size_t N>
void myMethod ( const int (& intArray) [N] )
{
    std::cout << "Array of " << N << " ints\n";
    return;
}

EDIT: A possible way to avoid code bloat would be to have a function that takes a pointer and a size that does the actual work:

void myMethodImpl ( const int * intArray, size_t n );

and a trivial template that calls it, that will easily be inlined.

template <size_t N>
void myMethod ( const int (& intArray) [N] )
    { myMethodImpl ( intArray, N ); }

Of course, you'ld have to find a way to test that this is always inlined away, but you do get the safety and ease of use. Even in the cases it is not, you get the benefits for relatively small cost.

Jubbah answered 18/7, 2012 at 14:32 Comment(6)
While functional, this is not particularly elegant, because, if I call myMethod 100 different times with different sizes, I get 100 different functions. Instant code bloat. Depending on what the function actually does, the optimizer may be able to use a single function instead, but in most useful cases, I don't think that'll be true...Erubescence
@BoBTFish: thanks for this. Do you know if there is a solution to avoid accessing an element outside of the bounds of the array: int x = intArray[N];Nicholenicholl
@twalberg: this is a good point. What would you suggest? Maybe a more generic but lest robust method like the one I wrote in my initial post?Nicholenicholl
@KevinMOLCARD It's always a tradeoff... If I know that I only have a handful of N that I need to instantiate, I might take the route suggested originally in the answer by @BoBTFish. If there's potentially more, I would either take the alternative in his edit (passing the size as an extra argument), or maybe wrap the array and it's size in a small struct and pass a reference/pointer to that instead to avoid having too many parameters. As usual, there's no one-size-fits-all solution.Erubescence
I love this technique, and suggest it to all my junior devs. It's great to be able to capture a static C array (both address and size) and not just a decayed pointer, and worry about the size being out of sync.Sharecrop
You have code bloat if metaprogramming unfolds a lot of N. but if all your hand-made call sites uses different N, your code is already bloated. you're not making it grow so much with a function that's just one line. that's as many as you have call sites.Mainsail
U
8

Per 3.9.3:2

Any cv-qualifiers applied to an array type affect the array element type, not the array type (8.3.4).

and 8.3.4:1

Any type of the form “cv-qualifier-seq array of N T” is adjusted to “array of N cv-qualifier-seq T”, and similarly for “array of unknown bound of T”.

Also, per 8.3.5:5

After determining the type of each parameter, any parameter of type “array of T” or “function returning T” is adjusted to be “pointer to T” or “pointer to function returning T,” respectively.

That means that within a function taking an array parameter, the parameter type is actually a pointer, and because of 3.9.3:2 the pointer is non-cv-qualified:

void foo(const int parameter[10]) {
    parameter = nullptr;   // this compiles!
}

This does not affect the type of the function itself, because of another clause in 8.3.5:5

After producing the list of parameter types, any top-level cv-qualifiers modifying a parameter type are deleted when forming the function type.

Thus if you want to be able to pass an array with cv qualifiers, it must be by reference:

void foo(const int (&parameter)[10]);
Unregenerate answered 18/7, 2012 at 14:58 Comment(0)
D
5

If you need the size of the array:

template < std::size_t Size >
void myMethod( const int ( &inTab )[ Size ] );
Dmso answered 18/7, 2012 at 14:29 Comment(0)
C
5

Not sure if it's what you asked about, but maybe it's what you were looking for

void func (const int array[10])
{
    //array[0] = 12345; // this wouldn't compile, so 'const' works
}

int main ()
{
    int array[10];
    func(array);
}
Confrere answered 18/7, 2012 at 14:38 Comment(2)
array = 0 would compile though, which OP doesn't want.Pershing
@a3f, why wouldn't he want it? array=0 inside func would not affect it outsideTrichomonad
S
-1

Try std::vector

void myMethod(const std::vector<int> &inTab);
Significancy answered 10/12, 2021 at 15:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.