Topic: Default assignment operator and arrays


Author: jbuck@forney.berkeley.edu (Joe Buck)
Date: 24 Apr 1992 03:03:56 GMT
Raw View
The discussion is about rules for the default assignment operator.

In article <1992Apr23.223713.17511@microsoft.com>, jimad@microsoft.com (Jim ADCOCK) writes:
|> In which case objects with array members cannot be assigned to each
|> other since assignment is illegal on arrays?  I still believe this
|> issue needs to be cleaned up, although some claim otherwise.  At the
|> very least, "memberwise" assignment on array members should be defined
|> to mean "bitwise assignment" -- although that begs the question why fixed
|> length arrays are not assignable?

I think it's fairly clear what the rule is supposed to be, by extension
from the rule for assignment of structs in C.  Array members are copied
element-by-element.  If the array is an array of a class with an assignment
operator, you want element-by-element assignment.

So the memberwise assignment rule is almost right: it just needs a minor
modification to document what's already done in practice for arrays to be
rigorously correct.

I think you know why fixed-length arrays aren't assignable, Jim; it's the
conversion to pointer that C does, so that

 int x[20], y[20];
 ...
 x = y;

doesn't work because "y" in this context is an int* const, the address of
y[0].

It seems to me that we might be able to fix this without breaking
compatibility with C, though, though I doubt if the committee could
be convinced to go along.  What if we did the conversion from array
to pointer in two stages: array-name -> reference, and reference -> pointer?
The idea is that arrays are passed to functions by reference, and there
is also a standard conversion from type "foo& y[n]" to type "foo*".
We can then pass an array to any function that takes a pointer argument
and have it work, and also permit array assignment and better type-checking
as well as having typedefs that use arrays, and templates where the argument
types are arrays, work correctly.  I don't think it would take that much
to make arrays a first-class type.

under the new rules, given the declaration

void func(int array[23]);

it wouldn't be legal to pass an int* to this function.  But if the
declaration were

void func(int *p);

or

void func(int array[]);

use of an int* OR use of an array would be legal (formal array arguments
of unspecified size would be considered to be pointers).  However, arrays would
be passed by reference by default; to say otherwise would break lots of
existing programs.

The only programs that would break would be those that declared a specific
size for a formal array parameter and then proceeded to pass arrays of
a different size to the function.  I don't think this would be very many.
Conversion of such programs would be easy: just delete any sizes.

Code like the following:

 char buf[BUFSIZE], *currentChar;
 currentChar = buf;

would still work the same way, because of the standard conversion of
array-name to pointer-to-first-element.  But this would now be a conversion
that loses information, like assigning a derived class pointer to a base
class pointer.  The information would not be thrown away in contexts where
this is not necessary.

To be more formal about this: what if an array of N elements of type Foo
were exactly equivalent to

 class Foo_N {
  Foo data[N];
 public:
  operator Foo*() { return data;}
  Foo& operator[](int i)
  { // compile-time range check: i in [0:N-1]
    // no run-time range checking
   return data[i];
  }
 };

with assignment operator that copies each element?  There may be other
things I haven't thought of.

It's too bad that it's too late to permit arrays to be passed by value,
but I rarely pass large objects by value anyway.  We could permit
arrays to be returned by value, perhaps, but that's assymmetrical.


--
Joe Buck jbuck@ohm.berkeley.edu




Author: jimad@microsoft.com (Jim ADCOCK)
Date: 27 Apr 92 04:50:26 GMT
Raw View
In article <t7tqsINNke8@agate.berkeley.edu> jbuck@forney.berkeley.edu (Joe Buck) writes:
|I think you know why fixed-length arrays aren't assignable, Jim; it's the
|conversion to pointer that C does, so that
|
| int x[20], y[20];
| ...
| x = y;
|
|doesn't work because "y" in this context is an int* const, the address of
|y[0].

Indeed this is what C does.  Its not what C++ does.  C++ only implicitly
coerces from an int[20] to an int* in situations that demand an int*.
Otherwise the int[20] remains an int[20].  Therefore, it would seem that
C++ could allow the assignment between x and y.