views:

154

answers:

3
+6  Q: 

std::string x(x);

std::string x(x);

This crashes very badly on my compiler. Does this mean I should test for this != &that in my own copy constructors, or can I assume that no client will ever be so stupid?

+7  A: 

You should not test against code that tries to crash badly. See Null References. It says

"Just as you must assume that a non-null pointer is valid, you must assume that a reference is valid. You must have faith in your fellow programmers."

I want to complement

... you must assume that the source of a copy is valid.

If you "fix" your case, what to do for this one?

string x = string(x);
Johannes Schaub - litb
+1  A: 

That code is not correct according to the standard and it does not make sense to check it and the best thing that can happen is a fast failure so that the user can correct their code.

David Rodríguez - dribeas
+3  A: 

Initializing something with itself is undefined behavior, which probably might even mean that once it is invoked you even can't detect it later. Suppose the compiler detects it and out of spite generates assembly for nasal demons, not a call to your copy constructor at all?

In practice, you can assume that the client is not that stupid, and if they are it is their business to debug it and figure it out.

UncleBens
Where exactly does the standard say that this is undefined behavior?
FredOverflow
Honestly, I'm surprised it even compiles. The problem is, `std::string`'s copy constructor is going to try to call methods/access data in `x`, but `x` has not been constructed yet. Therefore it's undefined behavior because it'd be trying to do things with a variable which has not been constructed yet.
Billy ONeal
@FredOverflow: I think one part of the standard that is relevant is the "point of declaration" (3.3.1). It is also possible that this has some meaningful uses, e.g suppose that the class stores a reference to another instance of the class (or itself), then we could do for example: `X x("self", x); X y("other", x);` etc. In such case, I suppose the rules would be similar as to using **this** in a class initialization list.
UncleBens
@FredOverflow, For your own classes, i don't think the Standard makes it undefined. You could do `struct X { X(X X x(x);` although such a class is not really useful, i think :) For standard classes, it's made undefined by "17.4.3.7 Function arguments".
Johannes Schaub - litb