views:

957

answers:

6

Hi all,

I recently wrote a piece of code which did

SomeClass someObject;
mysqlpp::StoreQueryResult result = someObject.getResult();

where SomeClass::getResult() looks like:

mysqlpp::StoreQueryResult SomeClass::getResult()
{
mysqlpp::StoreQueryResult res = ...<something>...;
return res;
}

Now, using the example in the first code snippet, when I compiled and ran, the program crashed with an ABORT signal. I then changed the first snippet to:

SomeClass someObject;
mysqlpp::StoreQueryResult result(someObject.getResult());

which worked fine. Also, just to try it out, I changed it again to:

SomeClass someObject;
mysqlpp::StoreQueryResult result;
result = someObject.getResult();

which also worked fine.

Now, I just can't figure out why the first example failed, and the next two succeeded. As I understand, in the first example, the copy constructor is used to initialise result. But isn't this also the case in the second example? So why did the second example succeed? The 3rd example makes a bit more sense - since the copy const isn't used, we just assign after construction.

In short, what's the difference between:

FooClass a = someObject.someMethodReturningFooClassInstance();

and

FooClass a(someObject.someMethodReturningFooClassInstance());?

Muchos thanks!

+4  A: 

I don't think there's any difference in the two cases. The same copy constructor is called both times.

Are you sure this is exactly what you've written in your code?

Frederick
Hi Frederick - thanks. I did a make clean and recompiled the whole thing, and now all 3 cases work fine. No idea why it failed before.
el_champo
Actually, there is a great difference between them. As others have already pointed out, in one case only the copy constructor is called, while in the other case what is called is the default constructor, and then the assignment operator. It's not the same at all.
Marc
@ Marc: Nope. When you call '=' during declaration, C++ will always call the copy constructor. Emphasis on always.
Marcin
It's exactly the same - but only if the right side has the same type as the left side and the copy constructor is not explicit.
Johannes Schaub - litb
+1  A: 

You could just put a breakpoint (or even a printf statement) inside the copy constructor, and you'd know exactly when it was called, you know. SO can't replace basic debugging. ;)

But yes, the copy constructor should be called in the two first cases. The third case uses the assignment operator instead.

Have you tried running it in the debugger? It should break on an ABORT signal.

jalf
Of course, putting a printf in a copy ctor will mess with the optimizer, which is likely involved
MSalters
+2  A: 

Strictly speaking in the first case the default constructor is called followed by the assignment operator and in the second case it uses just the copy constructor.

Okay, my initial assumption was wrong, and apparently in both cases just the copy constructor would get called (well in the assignment case an additional "conversion" constructor may be called as well). I'll fire up the compiler after some sleep and verify this in my development environment.

Daemin
In statements of the form T t = (Texpr), the assignment operator isn't used. Aka copy-initialization, cf. direct-initialization
MSalters
Out of interest do you have a link to the spec where it says that? I've always coded the direct copy constructor method because I read somewhere that the other form causes the default constructor and assignment operator to be called, hence less efficient.
Daemin
MSalters
Okay, thanks for that link. I guess it's one of my holdovers from using an old compiler.
Daemin
A: 

In the purest theory, the copy constructor should be called in both cases. However, there is something called Return Value Optimization (RVO) which the compiler is allowed to use in these cases. If RVO is used, the copy constructor will not be called. Perhaps your compiler uses RVO in one case and not the other?

Edit: This only applies to the case

SomeClass someObject;
mysqlpp::StoreQueryResult result;
result = someObject.getResult();
erikkallen
Constructors don't return anything. So there's no question RVO here.
Frederick
A: 

Well actually, the first one will do an intermediate copy with operator=, while the second one will do a direct copy construct.

Henrik Hartz
No first one is an initialization not assignment. So will use Copy constructor.
Martin York
A: 

I think first case is assigned value(right value) to object.It's send value to object.In 2,3 exmple is Implicit object and Explicit object concept.You not should write code by assigned value to direct object.

Chatsiri.rat