1

Consider the following code:

#include <iostream>
using namespace std;
class loc 
{
    int longitude, latitude;
    public:
        loc() {}
        loc(int lg, int lt) 
        {
            longitude = lg;
            latitude = lt;
        }
        loc(const loc& l)
        {
            cout << "a" << endl;
        }
        loc operator = (loc op2)
        {
            longitude = op2.longitude;
            latitude = op2.latitude;
            return *this;
        }
        loc operator+(loc op2);
};
loc loc::operator+(loc op2) {
    loc temp;
    temp.longitude = op2.longitude + longitude;
    temp.latitude = op2.latitude + latitude;
    return temp;
}
int main()
{
    loc ob1(10, 20), ob2( 5, 30);
    ob1 = ob1 + ob2;
    return 0;
}

On compiling this program using the command: g++ file.cpp, the output was:

a
hello

And then compiling this program using the command: g++ -fno-elide-constructors file.cpp, the output was:

a
a
a
hello

My question is:

In the first case, why are two copy constructors elided?

Which copy constructors are elided anyways? Is there a different mechanism for = operator or + operator

EDIT

I know how the correct assignment operator or copy constructor should look like. Please answer why two copy constructors are elided in the above case rather than correcting the assignment operator.

tapananand
  • 4,392
  • 2
  • 19
  • 35
  • 1
    Copy constructors are elided because the standard specifically allows this behavior. – Alok Save Nov 16 '14 at 05:42
  • This class does not need a custom copy constructor and assignment operator. Your assignment operator is wrong as it should return a non-const reference. – Neil Kirk Nov 16 '14 at 05:44
  • @AlokSave: I am asking why two copy constructors are elided. Normally only one would be elided. – tapananand Nov 16 '14 at 05:44
  • Your assignment operator has undefined behavior. You're not returning anything from it and the return type is not void. – Benjamin Lindley Nov 16 '14 at 05:47
  • @BenjaminLindley: made the edit. Still getting the same output. – tapananand Nov 16 '14 at 05:50
  • http://en.wikipedia.org/wiki/Return_value_optimization – Neil Kirk Nov 16 '14 at 05:51
  • @NeilKirk: The post is already tagged RVO, my question is why two copy-elisions are occurring and where are they occurring. – tapananand Nov 16 '14 at 05:54
  • It's explained in the article. – Neil Kirk Nov 16 '14 at 05:55
  • @remyabel: I am not allowing multiple assignment operations like this: a = b = c – tapananand Nov 16 '14 at 05:57
  • Multiple assignment operations is just something permitted by C++ and you should, in general, support it and rely on the user of your class being sensible. What if someone has written a generic template function that uses this feature, and they want to use your class with it? They can't. Also it's interesting that your assignment operator takes the parameter by value, which is inefficient in this case. – Neil Kirk Nov 16 '14 at 05:59
  • Now your operator is back to incorrect return type again. Also you copy the new object twice. Pass by const reference. – Neil Kirk Nov 16 '14 at 06:02
  • @NeilKirk: Edited, but just to bring to notice, this is not a production code I am trying to get the concepts right. – tapananand Nov 16 '14 at 06:02
  • @TapanAnand Your assignment operator should return a reference, not an object. More precisely: `loc& operator = (const loc& op2) {//...// return *this;}` In addition, your copy constructor doesn't copy. This leads to bugs if you write a bogus copy ctor like that. – PaulMcKenzie Nov 16 '14 at 06:05

1 Answers1

1

One elided copy is the return from op+. RVO allows the result to be constructed directly in the final destination, omitting temp altogether. The elided copy is from temp.

The second elided copy is passing the result of op+, which is a temporary, to op=. Instead it arranges for the result of op+ to be directly constructed in the op2 parameter. This isn't RVO, just normal elision of temporaries.

Alan Stokes
  • 18,815
  • 3
  • 45
  • 64
  • If this is true, then also two copy constructors should be called - one for passing the argument by value to + and another for passing by value to =. But here only one copy constructor is called. – tapananand Nov 16 '14 at 09:24
  • The second elision I listed *is* the pass by value to op=. (Why don't you just look at the generated code?) – Alan Stokes Nov 16 '14 at 10:01
  • According to your answer, the first constructor that is elided is the temporary object created for return, which is directly constructed into the destination (which actually is the argument to = you are eliding in second paragraph). See this link: http://stackoverflow.com/questions/26937270/copy-constructor-not-called-when-initializing-an-object-with-return-value-of-a-f – tapananand Nov 16 '14 at 16:05
  • Yes. And that direct construction saves two copies, one for the return and one for passing the argument to the subsequent call. – Alan Stokes Nov 17 '14 at 03:28
  • If the construction for return is elided then it must be directly built into the destination, can you tell what is the destination in this case. Also how are the arguments to + and = constructed? – tapananand Nov 17 '14 at 05:44