A question on explicit copy constructors

J

jimmyi

Hi, friends, i've just encountered a problem on explicit copy
constructors, my friend was read that when a function returns a object
by value, the object can be created outside the function if it is
returned in the way "return-and-copy-construct", so one can prevent
temporary object being created once inside the function and again when
the function returns the same object, the code example can be this:

#include <iostream>
using namespace std;

struct foo {
foo() { cout << "contructor called.\n"; }
foo(const foo& f) { cout << "copy-constructor called.\n"; }
~foo() { cout << "destructor called.\n"; }
int i;
};


foo fun(const foo& f)
{
/*foo ff;
ff.i = f.i;
return ff;*/
return foo(f);
}

int main()
{
foo f(fun(foo()));
}

if return ff instead of foo(f), gcc makes no difference, but vc6 will
create another copy of parameter f when the funcion returns. talk
about this problem seems trivial because it relies on the fact that
compiler could take lot of optimization works behind the scenes, thus
different compilers may have different default optimization behavior
and the result thus differs.

but my friend tried the first aproach(i.e. return ff) and thought that
behavior seems inefficient(through the fact that vc6 doesn't make a
good guess and as a newbie), and thus he tried out a way to eliminate
the problem by what the phrase i was invented "return-and-copy-
construct"(i.e. return foo(f)), though this trivial problem is easy to
explain(i'll tell the him the fact later), but his question is now
become:

when the copy constructor was declared explicit, the code above just
can't be compiled.

and gcc 3.3.1 gives the following errors:

test.cpp: In function `foo fun(const foo&)':
test.cpp:13: error: no matching function for call to `foo::foo(foo)'

i was not very experienced and my learning on c++ was also in
progress, although searched many possible solutions and documents. the
answer seems still obscure, hope someone can give me a convictive
explanation about this, many thanks.

P.S.
i'm not the native english speaker and the words above may be
syntactically ill formed, parden for my bad english :)
 
I

Ian Collins

jimmyi said:
Hi, friends, i've just encountered a problem on explicit copy
constructors, my friend was read that when a function returns a object
by value, the object can be created outside the function if it is
returned in the way "return-and-copy-construct", so one can prevent
temporary object being created once inside the function and again when
the function returns the same object, the code example can be this:

Most (any decent) compilers will optimise away the temporary object.
This is known as return value optimisation, or RVO.
#include <iostream>
using namespace std;

struct foo {
foo() { cout << "contructor called.\n"; }
foo(const foo& f) { cout << "copy-constructor called.\n"; }
~foo() { cout << "destructor called.\n"; }
int i;
};


foo fun(const foo& f)
{
/*foo ff;
ff.i = f.i;
return ff;*/
return foo(f);
}

int main()
{
foo f(fun(foo()));
}

if return ff instead of foo(f), gcc makes no difference, but vc6 will
create another copy of parameter f when the funcion returns.

VC 6 is an old, pre-standard compiler.
but my friend tried the first aproach(i.e. return ff) and thought that
behavior seems inefficient(through the fact that vc6 doesn't make a
good guess and as a newbie), and thus he tried out a way to eliminate
the problem by what the phrase i was invented "return-and-copy-
construct"(i.e. return foo(f)), though this trivial problem is easy to
explain(i'll tell the him the fact later), but his question is now
become:

A good reason not to use old, pre-standard compilers!
when the copy constructor was declared explicit, the code above just
can't be compiled.

and gcc 3.3.1 gives the following errors:

test.cpp: In function `foo fun(const foo&)':
test.cpp:13: error: no matching function for call to `foo::foo(foo)'

That's what an explicit constructor does. With an explicit constructor,
you have to explicitly create an object, implicit conversions are blocked.
 
J

jimmyi

Thank you for your reply, Ian Collins. I'll take your advise not to
use the old vc6, but I still can't understand where that implicit
conversion take place, could you give me some more explanation, thank
you!
 
J

jimmyi

i.e. for example the following code segment:

class foo {
....
explicit foo(const foo& f) { }
....
};

foo fun(const foo& f)
{
return foo(f); // needs help here, where the implicit conversion take
place?
}
 
P

Pavel

jimmyi said:
Thank you for your reply, Ian Collins. I'll take your advise not to
use the old vc6, but I still can't understand where that implicit
conversion take place, could you give me some more explanation, thank
you!
There is no implicit conversions there. It is just that explicit
constructor can only be used to create an object in one of two situations:

1. Direct initialization (would be "foo f1; foo f2(f1);" in your case).

2. Explicit use of casts.

You may think the compiler is unhappy about foo(f) in your return
statement but this is not so; it is unhappy that it cannot "as if"
create an object one more time with a copy constructor while returning
foo from the function. It must be allowed to "as-if-call" a copy
constructor whether or not you called it at will before that -- but this
is not one of the above two enumerated cases which are the only one
where explicit constructor can be used to crate an object. Maybe the
following example will shed some light:

The below code compiles just fine. You see, I am fine when I call my
explicit C(int) constructor as a conversion but in order to return the
value from the function, I need a non-explicit copy constructor no
matter what. If I change copy constructor to explicit, the code will not
compile.

#include <iostream>
using namespace std;
class C {
int i_;
public:
explicit C(int i) : i_(i) {}
C(const C &c) : i_(c.i_) {}
int getI() const { return i_; }
};
ostream &operator<<(ostream &o, const C &c) { return o << c.getI(); }
C f() { return C(5);}

int main() {
cout << f() << '\n';
return 0;
}

Hope this will help
-Pavel
 

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,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top