Reputation: 41
Why is the output foo3
equal to 3
?
i would suggest, when bar(foo1)
is called, the function bar
creates a copy of foo1
on the stack, so it's value is equal to 0, when this value is returned, the copy-constructor for foo3
increments the value again so it should be 2?
Thanks in advance.
this is my code:
#include <iostream>
struct Foo {
Foo()
: x(0)
{
}
Foo(const Foo& foo)
: x(foo.x + 1)
{
}
int x;
};
Foo bar(Foo foo)
{
foo.x++;
return foo;
}
int main()
{
Foo foo1;
Foo foo2 = foo1;
std::cout << "A:" << foo1.x << std::endl;
std::cout << "B:" << foo2.x << std::endl;
Foo foo3 = bar(foo1);
std::cout << "C:" << foo3.x << std::endl;
}
output:
A:0
B:1
C:3
Upvotes: 1
Views: 348
Reputation: 10336
When you create the first foo1
, its x
is zero. The call to bar
passes by value, so it is copied - so the param in bar
has a value of 1. The function bar
itself increments x
further by 1, so it is now 2. Finally, the return statement once again returns by value, so there is another copy - thus the final x
is 3.
Note RVO does not apply here, because Foo
is not returning a local variable by value - rather it is returning a parameter, which must actually be copied.
From the standard [class.copy/31], circumstances under which copy elision is permitted, which specifically exclude cases where function parameters are returned:
— in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value
Upvotes: 0
Reputation: 543
When doing:
Foo foo2 = foo1;
you are calling the copy ctor, so foo2.x's value will be 1. Then when calling:
Foo foo3 = bar(foo1);
because you are not passing by reference the argument of 'bar' is created a copy of foo1 into bar using the copy ctor (x == 1). After that that copy's x member is incremented(x == 2) and at last is returned. When returning is not created an other copy because 'return value optimization'(still x == 2). Finally foo3 is initialized using again the copy ctor(x == 3).
Upvotes: 0
Reputation: 170
I believe there are three copy constructors at work here, the line foo2 = foo1
, the passing of foo1
into bar
, and the returning of foo1
from bar
.
Modifying your code makes it clear what is happening:
#include <iostream>
struct Foo {
Foo()
: x(0)
{
std::cout << "Constructor called" << std::endl;
}
Foo(const Foo& foo)
: x(foo.x + 1)
{
std::cout << "Copy constructor called" << std::endl;
}
int x;
};
Foo bar(Foo foo)
{
std::cout << "B2:" << foo.x << std::endl;
foo.x++;
return foo;
}
int main()
{
Foo foo1;
Foo foo2 = foo1;
std::cout << "A:" << foo1.x << std::endl;
std::cout << "B:" << foo2.x << std::endl;
Foo foo3 = bar(foo1);
std::cout << "C:" << foo3.x << std::endl;
}
Output:
Constructor called
Copy constructor called
A:0
B:1
Copy constructor called
B2:1
Copy constructor called
C:3
Upvotes: 1
Reputation: 238421
0 -> 1
You copy foo1
to the parameter of bar
.1 -> 2
You increment x
within bar
.2 -> 3
You copy bar
to the temporary return value.I count three increments.
Upvotes: 0