1

Here is one program taken from a textbook featuring copy constructors:

#include <stdio.h>
#include <conio.h>
#include <iostream>

using namespace std;

class point
{
    private:
        int x,y;
    public:
        point(int ox =0, int oy =0)
        {
            cout << " Make object" << this << endl;
            cout << " Using default constructor \n";
            x = ox, y = oy;
        }
        point(const point &p)
        {
            cout << " Make object" << this << endl;
            cout << " Using copy constructor \n";
            x = p.x, y = p.y;
        }
        void move(int dx, int dy);
        void display();
};

point fct(point a);

int main()
{
    point a(5,2);
    a.display();

    point b = fct (a);
    b.display();
    getch();
    return 0;
}

void point::move(int dx, int dy)
{
    x += dx, y += dy;
}

void point::display()
{
    cout << "Coordinates :" << x << " " << y << "\n";
}

point fct(point a)
{
    point b=a;
    //b.move(2,3);
    return b;
}

It should be noted that the copy constructor is of the form : point (const point &p) instead of point (point &p) (the latter is what's in the textbook, but couldn't compile so I had to switch to the first one, but still I can't understand why :( )

The textbook said that there will be 3 lines of "Using copy constructor" , corresponding to 3 calls to the copy constructor. I think the reason for that is, when you call: b = fct(a)

  1. The function "fct" makes a copy of a (pass-by-value), therefor one call

  2. The line : point b = a : again, a copy constructor is invoked

  3. The return value is then copied into b (the variable in main, not the one in fct) this is 3rd one.

However upon execution, there is only 2 calls. Can anyone give me a good explaination on this?

mpromonet
  • 11,326
  • 43
  • 62
  • 91
Dang Manh Truong
  • 795
  • 2
  • 10
  • 35
  • 3
    http://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization – Luchian Grigore Jun 26 '15 at 09:13
  • @Luchian Grigore : OK that's one question, I still don't get why it is invoked only 2 times instead of 3 – Dang Manh Truong Jun 26 '15 at 09:19
  • @LuchianGrigore Isn't it because the returned object from `fct` becomes an `rvalue` and is `moved` (using the move constructor) and not `copied`? – Hindol Jun 26 '15 at 09:27
  • The code in the post could be improved removing functions `move` & `display` that are not related to the question [How to create a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) – mpromonet Jun 26 '15 at 09:29
  • @DangManhTruong To get results similar to the book, you can try disabling copy elision. In `g++` it is done using the `-fno-elide-constructors` flag. – Hindol Jun 26 '15 at 11:19

1 Answers1

3

Two copies occur because Named Return Value Optimization (NRVO) elides one of the copies.

point fct(point a)
{
    point b=a;
    return b;
}

point b = fct (a);

The first copy is the one from the argument a in main to the parameter a in fct. This occurs because the point is taken by-value.

The second copy is from a to b inside func.

The copy which is elided is the one in returning b by value. In this case, b can be directly allocated into the b at the call site, so no copy takes place.

TartanLlama
  • 63,752
  • 13
  • 157
  • 193
  • Just curious. If we explicitly delete the move constructor, will the NRVO still happen? – Hindol Jun 26 '15 at 09:39
  • 1
    @Hindol NRVO will still happen even if the move constructor is explicitly deleted. If NRVO is performed the object will directly be created in the storage that it would otherwise be copied or moved to. http://en.cppreference.com/w/cpp/language/copy_elision – Xardaska Jun 26 '15 at 10:05