0

I was reading about C++ and found that array to normal non const pointer conversion ( technically called as decay) don't happen when we pass array by reference. Is there any reason behind this restriction ?

I know that in C99 there are three fundamental cases array decay happens, namely:

when it's the argument of the & (address-of) operator.

when it's the argument of the sizeof operator.

When it's a string literal of type char [N + 1] or a wide string literal of type wchar_t [N + 1] (N is the length of the string) which is used to initialize an array, as in char str[] = "foo"; or wchar_t wstr[] = L"foo";.

Furthermore, in C11, the newly introduced alignof operator doesn't let its array argument decay into a pointer either.

In C++, there are additional rules, for example, when it's passed by reference.

Thanks

anonymous
  • 1,920
  • 2
  • 20
  • 30
  • 2
    What would you expect it to decay to? – juanchopanza Oct 22 '15 at 18:17
  • I am not sure question is what's the rational behind putting this restriction, in some situation is make's thing hard like normal copy operation template void copy(const T& A, const T& B) for this template will give error when calling like copy("STACK","STACKOVERFLOW"), – anonymous Oct 22 '15 at 18:19
  • 3
    First you'd have to explain what restriction you're talking about. – juanchopanza Oct 22 '15 at 18:20
  • 1
    @anonymous What error are you getting? – NathanOliver Oct 22 '15 at 18:22
  • 1
    My intuition is that arrays decay into pointers because simply they cannot be passed by value, since they cannot be copied or assigned. Thus, they physically decay to a pointer that points to the first element of the array. Now I don't get the intuition behind of why a reference should decay to something. – 101010 Oct 22 '15 at 18:24
  • 2
    Also, an array doesn't decay when passed to the `sizeof` operator. – juanchopanza Oct 22 '15 at 18:25
  • 2
    Better question might be why are arrays so broken that `int x[4]` isn't copyable, but `struct { int x[4]; }` is... – Barry Oct 22 '15 at 18:25
  • @Barry 1. You couldn't copy structs either in K&R; 2. A struct's layout must be known to use it, so there is enough information present to copy a struct anywhere it can be used -- for an array we just need a type and an address to access the elements, so there is not enough information. One *could* require complete array type declarations for everything but that would be terribly inflexible. Arrays would be like structs where all elements have the same type. @Christian: That's exactly what happens in C++ with refs to arrays -- `f(int[4]&)` cannot take an `int[5]`. – Peter - Reinstate Monica Oct 22 '15 at 18:35
  • It's not a restriction. Quite the opposite. With a reference, the array size is preserved. If you want, you can still point to the first element. – Christian Hackl Oct 22 '15 at 18:35

2 Answers2

2

Array-to-pointer decay produces an rvalue. So, for obvious reasons it only makes sense in rvalue contexts.

Reference contexts are naturally lvalue contexts, which is why array-to-pointer decay would make no sense whatsoever in such contexts.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
0

The simple answer is type safety, which is one C++'s mainstays. The only reason why there's decay in some instances is C compatibility.

Paul Evans
  • 27,315
  • 3
  • 37
  • 54
  • 1
    What would it mean to decay to array when passed by reference anyway? – juanchopanza Oct 22 '15 at 18:27
  • @PeterSchneider Then the array wouldn't be passed by reference. – juanchopanza Oct 22 '15 at 18:39
  • It's not only C compatibility. Arrays would become near useless for function calls (sans templates, that is) because one could call a given function only with an array of a given length. As if the length of a vector was a template parameter to the template. – Peter - Reinstate Monica Oct 22 '15 at 18:40
  • @juanchopanza It's *already* passed by reference, of course, even in C. Poor man's ref, for sure. If you contrast passing an array arg with passing a struct arg it should become obvious. – Peter - Reinstate Monica Oct 22 '15 at 18:41
  • @PeterSchneider I have no idea what you're talking about. We're talking C++, so the meaning of "reference" actually matters. Passing a pointer is pass by value in C++. – juanchopanza Oct 22 '15 at 18:43
  • @juanchopanza If we take "reference" as a concept, for a second, then array decay to pointer in function calls and assignments amounts to passing the array "by reference", conceptually. (Not quite coincidentally C++ references are usually implemented as... nothing new here.) Changing the argument's elements inside the callee changes the caller's elements, too. That is not the case with structs which are aggregates as well, but properly passed by value. – Peter - Reinstate Monica Oct 22 '15 at 18:48
  • @PeterSchneider We're talking C++, so the meaning of "reference" actually matters. Passing a pointer is pass by value in C++. To use reference to mean something else is just introducing confusion for no reason. – juanchopanza Oct 22 '15 at 18:51
  • @juanchopanza Sorry, the conceptual term "reference" (as in "pass by reference", as opposed to "pass by value") existed long before C++ was conceived -- for example, in Algol68 -- and was the reason C++ references are called that, and not something else. I'm not making terms up. Yes, the meaning of "reference" matters, that's why I tried to be clear. Of course the pointer -- to the original array -- is passed by value; how else would you implement passing something conceptually as a reference? – Peter - Reinstate Monica Oct 22 '15 at 18:53
  • I have asked a question regarding the rationale for array decay and attempted an answer [here](http://stackoverflow.com/q/33291624/3150802). – Peter - Reinstate Monica Oct 23 '15 at 00:12