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.