argument passing by value and temporaries

D

dave_dp

Hi, I have just started learning C++ language..
I've read much even tried to understand the way standard says but still
can't get the grasp of that concept.

When parameters are passed/returned by value temporaries are
created?(I'm not touching yet the cases where standard allows
optimizations from the side of implementations to avoid copying)
If so, please quote part of the standard that says that.
Assuming it is true, I can imagine two cases such as:

struct X {
};

void foo(X b);

....

int main(int argc, char* argv[]) {
X a;
foo(a); // first case
foo(X()); // second one
}

In the first case temporary variable is created that is *copy*
constructed with 'a' object and upon function call 'b' object is itself
copy constructed with that temporary variable.. am I doing right
assumtions iff (When parameters are passed/returned by value
temporaries are created) ?
So copy .ctor is used two times here ?

In the second case X() expression that is rvalue of type X.. I'm not
sure as well about the terminology to use here... X() expression is not
temporary object right? it is just a rvalue(that is value initialized)
and temporary object of type X is *copy* constructed with that rvalue
and then 'b' object is also copy constructed from that temporary...

Same holds true for returning objects ?

Now, if everything holds true, implementators can avoid two phase
copying, like in first example instead to copy construct temporary with
'a' object and then to copy construct 'b' object with that temporary,
'b' object is directly copy constructed with the 'a' object?

And in second case X() doesn't create temporary but directly copy
constructs 'b' ?

TIA.
 
I

Ivan Novick

Hi, I have just started learning C++ language..
I've read much even tried to understand the way standard says but still
can't get the grasp of that concept.

When parameters are passed/returned by value temporaries are
created?(I'm not touching yet the cases where standard allows
optimizations from the side of implementations to avoid copying)
If so, please quote part of the standard that says that.
Assuming it is true, I can imagine two cases such as:

struct X {
};

void foo(X b);

...

int main(int argc, char* argv[]) {
X a;
foo(a); // first case
foo(X()); // second one
}

In the first case temporary variable is created that is *copy*
constructed with 'a' object and upon function call 'b' object is itself
copy constructed with that temporary variable.. am I doing right
assumtions iff (When parameters are passed/returned by value
temporaries are created) ?
I don't believe the C++ standard requires creating a temporary variable
and then using it to initialize the function parameter with the copy
constructor. It should require only initializing the function
parameter with the copy constructor being passed the function argument.
Where did you get the idea that a temporary is created? Can you quote
a verse in the standard?

As for actual implementation, as opposed to the standard, when you run
said code only one default constructor for your initial declarion of
'a', and one copy constructor call when you pass the argument is
actually made in gcc.
 
D

dave_dp

Ivan said:
Hi, I have just started learning C++ language..
I've read much even tried to understand the way standard says but still
can't get the grasp of that concept.

When parameters are passed/returned by value temporaries are
created?(I'm not touching yet the cases where standard allows
optimizations from the side of implementations to avoid copying)
If so, please quote part of the standard that says that.
Assuming it is true, I can imagine two cases such as:

struct X {
};

void foo(X b);

...

int main(int argc, char* argv[]) {
X a;
foo(a); // first case
foo(X()); // second one
}

In the first case temporary variable is created that is *copy*
constructed with 'a' object and upon function call 'b' object is itself
copy constructed with that temporary variable.. am I doing right
assumtions iff (When parameters are passed/returned by value
temporaries are created) ?
I don't believe the C++ standard requires creating a temporary variable
and then using it to initialize the function parameter with the copy
constructor. It should require only initializing the function
parameter with the copy constructor being passed the function argument.
Where did you get the idea that a temporary is created? Can you quote
a verse in the standard?

As for actual implementation, as opposed to the standard, when you run
said code only one default constructor for your initial declarion of
'a', and one copy constructor call when you pass the argument is
actually made in gcc.

When I was searching NG for this type of question that IMHO has been
asked many times, I saw in few of the posts that said temporaries are
created when passing/returning arguments by value.. I can't find these
posts right now, but does it matter anyways? I didn't say I read it
from standard, I just asked if it was really defined in standard that
way... Sorry for being unclear in my first post if it was understood
like that..

And can you provide a verse in the standard where it doesn't require so
? Or any other statement that implies that temporaries are not made
during argument passing/returing by value. I'm really confused about
that matter and I'm in need of clear explaination of standard maybe
with examples too...

Thank you in advance.
 
H

Howard

Ivan Novick said:
Hi, I have just started learning C++ language..
I've read much even tried to understand the way standard says but still
can't get the grasp of that concept.

When parameters are passed/returned by value temporaries are
created?(I'm not touching yet the cases where standard allows
optimizations from the side of implementations to avoid copying)
If so, please quote part of the standard that says that.
Assuming it is true, I can imagine two cases such as:

struct X {
};

void foo(X b);

...

int main(int argc, char* argv[]) {
X a;
foo(a); // first case
foo(X()); // second one
}

In the first case temporary variable is created that is *copy*
constructed with 'a' object and upon function call 'b' object is itself
copy constructed with that temporary variable.. am I doing right
assumtions iff (When parameters are passed/returned by value
temporaries are created) ?
I don't believe the C++ standard requires creating a temporary variable
and then using it to initialize the function parameter with the copy
constructor. It should require only initializing the function
parameter with the copy constructor being passed the function argument.
Where did you get the idea that a temporary is created? Can you quote
a verse in the standard?

Well, it does create a temporary object, but that object is the parameter
itself. It doesn't create a temporary and then create the parameter from
that.
As for actual implementation, as opposed to the standard, when you run
said code only one default constructor for your initial declarion of
'a', and one copy constructor call when you pass the argument is
actually made in gcc.

yep.

-Howrad
 
D

dave_dp

Howard said:
Ivan Novick said:
Hi, I have just started learning C++ language..
I've read much even tried to understand the way standard says but still
can't get the grasp of that concept.

When parameters are passed/returned by value temporaries are
created?(I'm not touching yet the cases where standard allows
optimizations from the side of implementations to avoid copying)
If so, please quote part of the standard that says that.
Assuming it is true, I can imagine two cases such as:

struct X {
};

void foo(X b);

...

int main(int argc, char* argv[]) {
X a;
foo(a); // first case
foo(X()); // second one
}

In the first case temporary variable is created that is *copy*
constructed with 'a' object and upon function call 'b' object is itself
copy constructed with that temporary variable.. am I doing right
assumtions iff (When parameters are passed/returned by value
temporaries are created) ?
I don't believe the C++ standard requires creating a temporary variable
and then using it to initialize the function parameter with the copy
constructor. It should require only initializing the function
parameter with the copy constructor being passed the function argument.
Where did you get the idea that a temporary is created? Can you quote
a verse in the standard?

Well, it does create a temporary object, but that object is the parameter
itself. It doesn't create a temporary and then create the parameter from
that.
As for actual implementation, as opposed to the standard, when you run
said code only one default constructor for your initial declarion of
'a', and one copy constructor call when you pass the argument is
actually made in gcc.

yep.

-Howrad

Howard,

Can you clarify what do you mean when you say "Well, it does create a
temporary object, but that object is the parameter itself" Are you
saying that parameters are temporary objects that doubles up my
confusion ?

At any rate can anybody provide clear definition, maybe quotation(s)
from standard that answers my questions?

TIA.
 
H

Howard

Howard,

Can you clarify what do you mean when you say "Well, it does create a
temporary object, but that object is the parameter itself" Are you
saying that parameters are temporary objects that doubles up my
confusion ?

When passing an object by value, the object specified in the function call
(i.e., being "passed") is actually copied into a temporary object which is
created in automatic memory (or "on the stack", if you prefer). Inside the
called function, any reference to the parameter (i.e, any use of its name in
the source code) refers to that temporary object. So any changes to the
parameter object inside that function actually changes the temporary object
that was created. After the function returns, the temporary is destroyed
and those changes are lost.

If the object is passed by reference, however, then any use of the parameter
inside the function is actually affecting the object that was specified when
calling the function, not a temporary copy made from it.

-Howard
 
D

dave_dp

Howard said:
When passing an object by value, the object specified in the function call
(i.e., being "passed") is actually copied into a temporary object which is
created in automatic memory (or "on the stack", if you prefer). Inside the
called function, any reference to the parameter (i.e, any use of its name in
the source code) refers to that temporary object. So any changes to the
parameter object inside that function actually changes the temporary object
that was created. After the function returns, the temporary is destroyed
and those changes are lost.

If the object is passed by reference, however, then any use of the parameter
inside the function is actually affecting the object that was specified when
calling the function, not a temporary copy made from it.

-Howard

So, what happens in second example?
foo(X()); based on what you said b is directly copy constructed by X()
? Does it hold true when returning by value and when throwing an
exception? for example

X foo() {
X c;
return c;
}

....
X a = foo(); // Is a directly copy constructed by c ? and if so then
what's difference between optimized implementation and not optimized
one if argument passing/returning by value directly copy constructs
objects...

Now as far as exceptions are concerned, as I've read throw T() causes
always temporary object to be created and copy constructed by T() and
in catch clause(s) it is caught by reference or object is copy
constructed by that temporary depending how catch clause is
written(T&,T).. why it is any different from parameter passing by value
or returning by value ? and what kind of a optimization can
implementation offer ? I'm still in state of confusion, and would
appreciate if anybody could shed some light in my understanding of
these concepts.

TIA.
 
P

Pete C

Howard said:
When passing an object by value, the object specified in the function call
(i.e., being "passed") is actually copied into a temporary object which is
created in automatic memory (or "on the stack", if you prefer).

Howard, I think you are using a looser definition of 'temporary' than
either Ivan or the Standard (if - as it seems - you are applying it to
automatic variables in general). Section 12.2 covers the creation of
temporary objects, and function parameters aren't in the list.

Ivan, even in your second case you only have 1 copy constructor at
most:
1) Default construct your temporary X.
2) Copy construct your function parameter from the temporary.
As you mentioned the compiler is allowed to default construct the X
directly in-place. If you have g++, play around with the
-fno-elide-constructors switch.

I think the confusion arose because you thought that X() doesn't
construct a temporary variable - it does. From Section 5.2.3:
"... the expression T(x1, x2, ...) is equivalent in effect to the
declaration T t(x1, x2, ...); for
some invented temporary variable t, with the result being the value of
t as an rvalue."
 
P

Pete C

X foo() {
X c;
return c;
}

...
X a = foo();

Here:
1) c is default constructed
2) the temporarary for the return value is copy-constructed from c
3) a is copy constructed from the temporary.

But the optimisations mean that either or both of the copy
constructions can be eliminated. I expect that you modified your
example from section 12.8.15 of the standard, but in case you didn't:
read that section, it is helpful.
Now as far as exceptions are concerned, as I've read throw T() causes
always temporary object to be created and copy constructed by T()

This *can* happen, but as above, the copy construction may be optimised
away.
in catch clause(s) it is caught by reference or object is copy
constructed by that temporary depending how catch clause is
written(T&,T).. why it is any different from parameter passing by value
or returning by value ?

It isn't any different, except that the temporary is (or would be)
created without the cv qualifiers - this means that you can throw an
rvalue and catch a non-const reference. You wouldn't be able to do this
in normal parameter passing. Other than that, it's like calling a
funcion.
and what kind of a optimization can
implementation offer ?
From section 12.5 again:

"- in a return statement in a function with a class return type, when
the expression is the name of a non-volatile automatic object with the
same cv-unqualified type as the function return type, the copy
operation can be omitted by constructing the automatic object directly
into the function's return value
- when a temporary class object that has not been bound to a reference
(12.2) would be copied to a class object with the same cv-unqualified
type, the copy operation can be omitted by constructing the temporary
object directly into the target of the omitted copy"
 
V

Vidar Hasfjord

When parameters are passed/returned by value temporaries are
created?

Yes. I just want to add to other replies that it may be useful for
understanding to manually inline the function call. Here's an extended
example illustrating by-value parameter passing and return values:

struct X {
X (int);
friend X operator + (X, X);
};

void foo(X param) {
cout << param;
}
X bar (X param) {
X local = param + X (1);
return local;
}

int main () {
X a (1);
X b (2);

// foo (a);
// -----------------------------
{
// --- Parameter setup
X param (a);
// --- Call
cout << param;
}

// foo (X ());
// -----------------------------
{
X _tmp ();
// --- Parameter setup
X param (_tmp);
// --- Call
cout << param;
}

// X c = bar (a + b);
// -----------------------------

X c; // #1a
{
// --- Evaluate expression
X _tmp (a + b);
// --- Return value setup
X _bar_return; // #2a
// --- Parameter setup
X param = _tmp;
// --- Call
X local = param + X (1);
_bar_return = local; // #2b
// --- Assignment
c = _bar_return; // #1b
}
}

The parameter return mechanism above is a simplification though. To
avoid superfluous constructor calls the actual implementation of #1a
and #1b would be more like this:

// #1a - uninitialized allocation
char _c_flesh [sizeof C];
X& c = *reinterpret_cast <X*> (&_c_flesh);

// #1b - placement construction
new (&c) X (_bar_return); // copy construct into c

Similarily for #2a and #2b.
X a = foo(); // Is a directly copy constructed by c ? and if so then
what's difference between optimized implementation and not optimized
one if argument passing/returning by value directly copy constructs
objects.

Ok, let's consider return-value optimization (RVO) for the last
function call. It is very similar, except that the compiler recognizes
that "local" and "_bar_return" can be merged and that the result can be
constructed in c directly:

// X c = bar (a + b);
// -----------------------------

X c;
{
// --- Evaluate expression
X _tmp (a + b);
// --- Return value setup
X& _bar_return = c; // #1
// --- Parameter setup
X param = _tmp;
// --- Call
X& local = _bar_return; // #2
local = param + X (1);
}

The optimization happens at #1 and #2 where "_bar_return" and "local"
now are just aliases for c. In essence the code now is equivalent to:

// X c = bar (a + b);
// -----------------------------

X c;
{
// --- Evaluate expression
X _tmp (a + b);
// --- Parameter setup
X param = _tmp;
// --- Call
c = param + X (1);
}

The standard allows this optimization by not requiring that temporary
objects are created. That means that compliant code should not depend
on constructors being called in a deterministic sequence (e.g. a
certain number of times).
 
I

Ivan Novick

Hi, I have just started learning C++ language..
I've read much even tried to understand the way standard says but still
can't get the grasp of that concept.

When parameters are passed/returned by value temporaries are
created?(I'm not touching yet the cases where standard allows
optimizations from the side of implementations to avoid copying)
If so, please quote part of the standard that says that.
Assuming it is true, I can imagine two cases such as:

struct X {
};

void foo(X b);

...

int main(int argc, char* argv[]) {
X a;
foo(a); // first case
foo(X()); // second one
}

Had a chance to check the standard and read all the other posters
comments, here's my conclusion:

// no temporary is created
// (unless you call the parameter itself a temp)
// see sections [5.2.2.4] and [12.2] and [6.6.3]
foo(a);

// a temporary is created to return back to the calling program
return a;

// However the temporary may not actually be created if the
// return value is assigned into an object, and compiler can
// directly copy construct with object being returned.
X b = foo();

// an object is created on the stack and default constructed
// said object is passed by value and used as argument to
// copy constructor essentially this is same case as foo(a)
// but you are creating the object and passing it
foo(X());

I am feeling about 97% confident about above statements so feel free to
shoot at it if you see something wrong.
 
D

dave_dp

Pete said:
Here:
1) c is default constructed
2) the temporarary for the return value is copy-constructed from c
3) a is copy constructed from the temporary.

But the optimisations mean that either or both of the copy
constructions can be eliminated. I expect that you modified your
example from section 12.8.15 of the standard, but in case you didn't:
read that section, it is helpful.


This *can* happen, but as above, the copy construction may be optimised
away.


It isn't any different, except that the temporary is (or would be)
created without the cv qualifiers - this means that you can throw an
rvalue and catch a non-const reference. You wouldn't be able to do this
in normal parameter passing. Other than that, it's like calling a
funcion.



"- in a return statement in a function with a class return type, when
the expression is the name of a non-volatile automatic object with the
same cv-unqualified type as the function return type, the copy
operation can be omitted by constructing the automatic object directly
into the function's return value
- when a temporary class object that has not been bound to a reference
(12.2) would be copied to a class object with the same cv-unqualified
type, the copy operation can be omitted by constructing the temporary
object directly into the target of the omitted copy"

Pete, Vidar, Ivan thank you very much it is all clear now.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top