1

I wrote this:

#include <iostream>

struct A
{
    int a;
    int b;
    A() : a(10) { std::cout << "default ctor" << std::endl;}
    ~A(){ }
    A(const A&){ std::cout << "copy ctor" << std::endl; }
    A(const A&&){ std::cout << "move ctor" << std::endl; }
};

A init()
{
    A a;
    a.b = 20;
    return a;
}

int main()
{
    A a = init();
    std::cout << a.b << std::endl;
}

I expected that A a = init() imposes the move-contructor call, but the outpur is:

default ctor

20

DEMO

St.Antario
  • 26,175
  • 41
  • 130
  • 318
  • `RVO` is compiler dependent - VS2012 in debug works as you would expect, but in release it behaves the same as your demo, so compiler decides inlining is better. – Rudolfs Bundulis Jul 15 '15 at 09:16

1 Answers1

1

The line

A a = init();

is inlined by NRVO. It creates an object by using it's default constructor in its segment of code:

A a;

Your move constructor will not be used here.

The move constructor here can be used with -fno-elide-constructors compiler flag. I've modified your example to compile it with this flag. But note, that default constructor will always be called because NRVO does not affect this in your code. NRVO only means that the object will be constructed in the storage that it is needed (not on the stack of your init method) so it would not be moved or copied. With the no-elide flag it can't be created there so it would be copied/moved there.

VP.
  • 15,509
  • 17
  • 91
  • 161