By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,116 Members | 1,309 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,116 IT Pros & Developers. It's quick & easy.

which on is correct?~about temp object~

P: n/a
hi, all,
i'm reading ch.20 -smart pointers- of [C++ Template].
and i'm tring the trule.hpp test. but there's something different
than i expect, and i found that's about temp object. so i simplified
the question into the following code:

===code starts===
#include <iostream>
using namespace std;

class H
{
public:
H(int i){ cout << "h" << endl; }
};

class T
{
public:
T(int i){ cout << "t" << endl; }
T(H& h){ cout << "ht" << endl; }
T(T const & rhs){ cout << "tt" << endl; }
};

T foo()
{
int i = 10;
return i;
}

T bar()
{
H h(11);
return h;
}

int main()
{
T t1(foo());
T t2(bar());
return 0;
}
===code ends===

on my win2k box, i both use bcb and devc++ to test it:
===bcb output===
t
tt
h
ht
tt
===devc++ output===
t
h
ht
=============

well, i though bcb was right, cause both foo() and bar() generate
temp obj, and which should be use to copy contruct the return T.

anyway, i want to know which is correct, i mean, std compliant.
if it's not bcb, why?

thanks.

Jul 23 '05 #1
Share this Question
Share on Google+
11 Replies


P: n/a
cf****@gmail.com wrote:
i'm reading ch.20 -smart pointers- of [C++ Template].
and i'm tring the trule.hpp test. but there's something different
than i expect, and i found that's about temp object. so i simplified
the question into the following code:

===code starts===
#include <iostream>
using namespace std;

class H
{
public:
H(int i){ cout << "h" << endl; }
};

class T
{
public:
T(int i){ cout << "t" << endl; }
T(H& h){ cout << "ht" << endl; }
T(T const & rhs){ cout << "tt" << endl; }
};

T foo()
{
int i = 10;
return i;
}

T bar()
{
H h(11);
return h;
}

int main()
{
T t1(foo());
T t2(bar());
return 0;
}
===code ends===

on my win2k box, i both use bcb and devc++ to test it:
===bcb output===
t
tt
h
ht
tt
===devc++ output===
t
h
ht
=============

well, i though bcb was right, cause both foo() and bar() generate
temp obj, and which should be use to copy contruct the return T.

anyway, i want to know which is correct, i mean, std compliant.
if it's not bcb, why?


I think both are OK. During initialisation, the compiler is allowed
to forgo creation of a temporary like that and initialise directly into
the object. How they do it? I don't know. Examine the assembly code
and you will probably find out that most of the member functions have
been inlined and the initialisation goes directly into the object
without copying.

May be worth to mention that while compiler is allowed to skip the
creation of a temporary in certain contexts, the possibility should
still exist. For example, if you declare the copy constructor for
your class T private, the code shouldn't compile even with devc++
since the copy cannot be made (even though the compiler can create
code that doesn't require creation of a copy).

V
Jul 23 '05 #2

P: n/a
* cf****@gmail.com:
[snip example]
anyway, i want to know which is correct, i mean, std compliant.
if it's not bcb, why?


As an alternative explanation to Victor's, you might choose to think about
this as primarily being about copy constructors, not temporaries.

A copy constructor is the only member function that is required to do one
thing and one thing only: to copy the argument into the current
to-be-constructed object.

The compiler is allowed to assume that a copy constructor does what it's
supposed to, not more, and not less. And on that basis -- without
considering the actual code you've placed in in a copy constructor -- the
compiler can replace or remove calls if that leaves the final effect
unchanged. So if a copy constructor does something more than it's supposed
to, then those actions are not guaranteed to be executed.

Thus, any C++ questionnare that asks you to count the number of copy
constructor calls is questionable... ;-)

And so are attempts at optimizing away copy constructor calls. Typically
the simplest code will be optimized very well by the compiler, those darned
copy operations removed. But "clever" code can end up with no optimization.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #3

P: n/a
Alf P. Steinbach wrote:

The compiler is allowed to assume that a copy constructor does what
it's supposed to, not more, and not less. And on that basis --
without considering the actual code you've placed in in a copy
constructor -- the compiler can replace or remove calls if that
leaves the final effect unchanged. So if a copy constructor does
something more than it's supposed to, then those actions are not
guaranteed to be executed.


I think that only applies to RVO and NRVO. In other cases,
the compiler must execute all of the copy constructor's
side effects etc. If it calls the copy constructor multiple times,
then it must do the side effects multiple times.

Jul 23 '05 #4

P: n/a
* Old Wolf:
Alf P. Steinbach wrote:

The compiler is allowed to assume that a copy constructor does what
it's supposed to, not more, and not less. And on that basis --
without considering the actual code you've placed in in a copy
constructor -- the compiler can replace or remove calls if that
leaves the final effect unchanged. So if a copy constructor does
something more than it's supposed to, then those actions are not
guaranteed to be executed.


I think that only applies to RVO and NRVO. In other cases,
the compiler must execute all of the copy constructor's
side effects etc. If it calls the copy constructor multiple times,
then it must do the side effects multiple times.


As a simple non-RVO/NRVO example,

SomeClass x = SomeClass( 123 );

Here the temporary and copy constructor can be elided, according to our holy
standard.

And so on.
Cheers,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #5

P: n/a
Alf P. Steinbach schreef:
any C++ questionnare that asks you to count the number of copy
constructor calls is questionable... ;-)


Well, there are two situations that are definitely distinct:
==0 and >=0. The first doesn't require an accessible copy ctor.
The second one does.

I'm afraid the number of quizzes that have these options
is a bit low, though.

Regards,
Michiel Salters

Jul 23 '05 #6

P: n/a
sorry, i don't really get it. may you explain the two situations,
thanks a lot.
i reviewed the "inside the c++ object model", which deeply explains
copy constructor and NRV.

And I hope the following conclusion is right:
the NRV is used to improve efficiency without actually invoking the
copy constructor.
and for Als' example:
SomeClass x = SomeClass( 123 );
if NRV is applied, it won't be:
SomeClass temp.SomeClass::SomeClass(123);
SomeClass x.SomeClass::SomeClass(temp); //copy constructor
instead, it'll be:
SomeClass x.SomeClass::SomeClass(123); //x substitutes temp, and
construct directly in the x's space

thank you.

Jul 23 '05 #7

P: n/a
Alf P. Steinbach wrote:
* Old Wolf:
Alf P. Steinbach wrote:

The compiler is allowed to assume that a copy constructor does what
it's supposed to, not more, and not less. And on that basis --
without considering the actual code you've placed in in a copy
constructor -- the compiler can replace or remove calls if that
leaves the final effect unchanged. So if a copy constructor does
something more than it's supposed to, then those actions are not
guaranteed to be executed.


I think that only applies to RVO and NRVO. In other cases,
the compiler must execute all of the copy constructor's
side effects etc. If it calls the copy constructor multiple times,
then it must do the side effects multiple times.


As a simple non-RVO/NRVO example,

SomeClass x = SomeClass( 123 );


How about:

void foo(SomeClass const &);

int main()
{
SomeClass a;
SomeClass b(a);
foo(b);
}

Can that copy-constructor and side-effect be elided because
the compiler determines that 'a' is never used again, and
it decides to simply use 'b' and 'a' to both refer to the same
bit of memory? If not, why not?

Jul 27 '05 #8

P: n/a
* Old Wolf:

How about:

void foo(SomeClass const &);

int main()
{
SomeClass a;
SomeClass b(a);
foo(b);
}

Can that copy-constructor and side-effect be elided because
the compiler determines that 'a' is never used again, and
it decides to simply use 'b' and 'a' to both refer to the same
bit of memory?


I could just give an answer, pretending to absolutely know such details, but
I think it's more honest to explain the process towards that answer.

1. I read your question and I'm _fairly sure_ the answer is yes, because of
what's commonly called the "as if" rule, and I'm planning to mention the
rather non-obvious requirement for a copy constructor, generated or
user-defined, when passing by ref to const (discovered during AA's Mojo
adventure), and also the difference when a and b's adresses might be used.

2. I plan to check the 1998 standard. But first, I make some coffee.

3. I discover that I'm almost out of coffee, and I've just been down to 7-11
and not very keen to make another trip, it takes twelve minutes each way.
What's needed to cancel the spiritual effects of this severe psychological
setback is evidently a bite of "Gullbrød" chocolate, favoured by our Prime
Minister. "Gullbrød", wolfed down (hah), one more cup of coffee, down.

4. Acrobat Reader informs me there's an update available. And not just one!
However, no matter what is selected it insists on also installing Yahoo
Toolbar. F**k off, Adobe. I don't want no sneaking malware Yahoo Toolbar,
_especially not_ one that cannot be deselected in the installation dialog.

5. OK, the "as if" rule, that's §1.9/1, "confirming implementations are
required to emulate (only) the observable behavior of the abstract machine
as explained below", where the key word is _observable_. §1.9/6 then
defines observable behavior as the "sequence of reads and writes to volatile
data and calls to library I/O functions", with a note explaining that
library I/O functions include such functions added by the implementation.
So already, given that copy constructors can be elided without regard to
their side-effects, this provides the answer "yes" to your question. But I
gather you're interested also in the copy constructor side-effect issue.

6. The possibility of ignoring side-effects in copy constructors is
mentioned twice in e.g. §12.8/15, about eliding temporaries for
initialization and function results, "even if the copy constructor or
destructor have side effects". So there I learned something new. Even
though it was implicit in what I already knew I hadn't really thought about
a destructor with side-effects, but there you are: neither copy constructor
nor destructor side-effects can be relied on in C++. It's all Andrei
Alexandrescu's fault, because as I recall he wrote in MC++D that the copy
constructor was special in this regard. But it's also destructors.

7. Regarding the requirement for a copy constructor to exist for passing by
reference to const, well, I don't find it. But I'm fairly sure it's there,
somewhere, even for C++2003. And also that it will be fixed in C++0x.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 27 '05 #9

P: n/a
Alf P. Steinbach wrote in news:42****************@news.individual.net in
comp.lang.c++:
* Old Wolf:

How about:

void foo(SomeClass const &);

int main()
{
SomeClass a;
SomeClass b(a);
foo(b);
}

Can that copy-constructor and side-effect be elided because
the compiler determines that 'a' is never used again, and
it decides to simply use 'b' and 'a' to both refer to the same
bit of memory?


6. The possibility of ignoring side-effects in copy constructors is
mentioned twice in e.g. §12.8/15, about eliding temporaries for
initialization and function results,


The keyword there is "temporaries", in the above neither "a" nor "b"
is a temporary so the copy-construction of "b" can't be elided, except
under the as-if rule, which can't happen if the copy-constructor (or
destructor, as you point out in the bit I snipped) has side effects.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 27 '05 #10

P: n/a
* Rob Williscroft:
Alf P. Steinbach wrote in news:42****************@news.individual.net in
comp.lang.c++:
* Old Wolf:

How about:

void foo(SomeClass const &);

int main()
{
SomeClass a;
SomeClass b(a);
foo(b);
}

Can that copy-constructor and side-effect be elided because
the compiler determines that 'a' is never used again, and
it decides to simply use 'b' and 'a' to both refer to the same
bit of memory?


6. The possibility of ignoring side-effects in copy constructors is
mentioned twice in e.g. §12.8/15, about eliding temporaries for
initialization and function results,


The keyword there is "temporaries", in the above neither "a" nor "b"
is a temporary so the copy-construction of "b" can't be elided, except
under the as-if rule, which can't happen if the copy-constructor (or
destructor, as you point out in the bit I snipped) has side effects.


Well, first, contrary to what your quoting indicates, is was the as-if rule
I primarily referred to.

However, you're right, but possibly for the wrong reasons?, that I drew an
incorrect conclusion.

The question Old Wolf posed turns out to be answered directly by the
standard:

§3.7.2/3: "If a named automatic object has initialization or a destructor
with side effects, it shall not be destroyed before the end of its block,
nor shall it be eliminated as an optimization even if it appears to be
unused, except that a class object or its copy may be eliminated as
specified in 12.8".

So, there's the definitive formal answer, but I don't think it's wise to
rely on that behavior in an actual compiler (especially considering 12.8).

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 27 '05 #11

P: n/a
Alf P. Steinbach wrote in news:42****************@news.individual.net in
comp.lang.c++:
> 6. The possibility of ignoring side-effects in copy constructors is
> mentioned twice in e.g. õ12.8/15, about eliding temporaries for
> initialization and function results,
The keyword there is "temporaries", in the above neither "a" nor "b"
is a temporary so the copy-construction of "b" can't be elided,
except under the as-if rule, which can't happen if the
copy-constructor (or destructor, as you point out in the bit I
snipped) has side effects.


Well, first, contrary to what your quoting indicates, is was the as-if
rule I primarily referred to.

However, you're right, but possibly for the wrong reasons?, that I
drew an incorrect conclusion.


I think both my highlighting of temporaries and your quote below are
needed for the picture to be complete.
The question Old Wolf posed turns out to be answered directly by the
standard:

õ3.7.2/3: "If a named automatic object has initialization or a
destructor with side effects, it shall not be destroyed before the end
of its block, nor shall it be eliminated as an optimization even if it
appears to be unused, except that a class object or its copy may be
eliminated as specified in 12.8".

So, there's the definitive formal answer, but I don't think it's wise
to rely on that behavior in an actual compiler (especially considering
12.8).


12.8/15 specifcaly mentions only 2 cases, first case creating the return
value of a function and the second case when a temporary is copied.

In the first case an rvalue (a form of temporary) is the destination
of the copy and in the second a temporary is the source of the copy.

In Old Wolf's example, both the source and destination of the copy
were named locals (in the same scope), so 12.8/15 can't apply.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 27 '05 #12

This discussion thread is closed

Replies have been disabled for this discussion.