Reputation: 1311
class C
{
public:
C(C& c)
{
i = c.i;
j = 100;
}
C() : i(0), j(0)
{
}
int i, j;
};
C func(C c)
{
return c;
}
int main()
{
C c;
c = func(c)
// What is the value of j?
}
Above is a class with an unusual copy constructor. Instead of copying i and j, it copies i and assigns something else to j. What happens when I pass an object of the class to the function?
Edit: It just seems like such a tricky thing to do in a program...
Upvotes: 1
Views: 281
Reputation: 477378
It is your responsibility to equip your class with a copy constructor such that the expression Foo x(y);
results in an object x
that is semantically equal to y
. Nobody forces you to do that in any particular way, and the program will behave as you tell it to.
Consider this simplified example:
struct Foo
{
int value;
explicit Foo(int n) : value(n) { }
Foo(Foo const & rhs) : value(rhs.n / 5 - 32) { } // tee-hee
};
Foo make_it_so() { return Foo(40); }
int main() { Foo k = make_it_so(); }
Now depending on whether the copy constructor is elided or not, k.value
ends up either with 40
or with -24
. However, because you wrote the copy constructor, you have essentially declared that you consider the two semantically equal.
C++ lets you set the rules of the game, but it doesn't protect you from going straight to jail.
(I know that my example is slightly different from what you asked in your question ("argument passing"), but it is intended to illustrate your responsibilities as an author.)
Upvotes: 1
Reputation: 59831
The obvious happens. The object is copied. The values are set to whatever you do in the copy constructor. You can confirm this by simply printing the values.
Copy-elision is not allowed here as the argument passed into the function is not an rvalue. If it were an rvalue (e.g. func(C())
) the code would not compile as the temporary cannot be bound to the copy constructor as it is taking a reference as argument and not a reference to const. If this is fixed, copy-elision can be observed for the argument and the return value. So the state of c
after being assigned to could be the one of a default constructed C
.
As far as I understand the code as shown will always show the same behavior and does not depend on optimizations.
Upvotes: 0
Reputation: 431
When you write a copy constructor with the same signature as the default copy constructor, you are suppressing the default one from being created.
So when the code calls for the default copy constructor it will run the one you have made and do whatever you put in there, be it printing, memory allocation, or even just do nothing if that is how you coded it.
Upvotes: 0
Reputation: 283733
The copy constructor may be called, in which case your weird behavior happens.
Or, the compiler may elide the copy (this is specifically allowed by the standard), breaking your expectations. In this particular case that isn't allowed, but in many contexts it is.
So don't write copy-constructors that do weird things. (Or else we will call you auto_ptr
)
Upvotes: 8