Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

constant arrays

Tags:

This is a good old C array:

int a[10];

And this is a good old C array that is const:

const int b[10];

In C++, there seem to be two ways to define std::arrays that are const:

std::array<const int, 10> c;
const std::array<int, 10> d;

Are these two definitions equivalent? If so, what is the idiomatic one? If not, what are the differences?

like image 424
fredoverflow Avatar asked Oct 17 '11 08:10

fredoverflow


2 Answers

Well, the original const int b[10]; is only useful when you can initialize the array, so both of the std::array examples don't work in practice.

1:

std::array<const int, 10> c;

This is the closest to const int c[10];. The problem is there will be no default constructor for it, and because the elements are not mutable, it's worthless to use this. You must provide some initialization for it in the constructor. As-is, it will give a compiler error because the default constructor did not initialize the elements.

This code means that c is mutable, but the elements themselves are not. In practice, however, there are no mutations on c that don't affect the elements.

2:

const std::array<int, 10> d;

This means d is not mutable, but the elements are of mutable type int. Because const will propagate to the members, it means the elements are still not mutable by the caller. Similar to the above example, you will need to initialize d because it's const.

In practice, they will both behave similarly with respect to mutability, because mutable operations on array always touch the elements.

like image 148
tenfour Avatar answered Sep 17 '22 09:09

tenfour


They aren't equivalent -- c.reference is int& whereas d.reference is const int& (not that you can use that syntax to access typedefs, but you could capture the type by template argument deduction and tell the difference).

But I'm pretty sure tenfour has the key observation, "there are no mutations on c that don't affect the elements". So as far as anything you actually do to the arrays is concerned they're the same, they just have different meta-data because of their different types.

The main case I can think of where it would make a difference is if you use the type itself in an interface (as opposed to taking an iterator or range template parameter). I'd say that when taking it as a pointer or reference parameter you should const-qualify the array type itself, since it costs you nothing and allows the caller to use your function whichever choice they made. You may const-qualify the element type, but whichever one you use is incompatible with the other one, so basically everyone has to agree which to use or else there will be some copying required. That requires active co-ordination as to style, I think, since I doubt that you'll get everyone in the world to agree which is best. const int probably has the better case, on the principle that you should const everything you can, but I expect int is what people will use who haven't thought about it at all, since they're used to all those C++03 containers that can't have a const value type.

like image 32
Steve Jessop Avatar answered Sep 19 '22 09:09

Steve Jessop