Peter McG
Peter McG

Reputation: 19045

Why doesn't the move constructor get called in this contrived example?

Shouldn't the un-named return value from GetPerson bind to the move constructor?

person.hpp

#ifndef PERSON_H
#define PERSON_H

#include <string>

struct Person {

    Person(std::string name, int age) : name(name), age(age) {
        std::cout << "ctor" << std::endl;
    }

    Person(const Person& rhs) : name(rhs.name), age(rhs.age) {
        std::cout << "copy ctor" <<  std::endl;
    }

    Person(Person&& rhs) : name(std::move(rhs.name)), age(std::move(rhs.age)) {
        std::cout << "move ctor" <<  std::endl;
    }

    ~Person() {
        std::cout << "dtor" << std::endl;
    }

    std::string name;
    int age;
};

#endif

main.cpp

#include <iostream>
#include "person.hpp"

Person GetPerson(std::string name, int age) {
    return Person(name, age);
}

int main(int argc, char* argv[]) {
    Person p(GetPerson("X", 21));
}

I'm using gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) and compiling with:

gcc -g -x c++ -lstdc++ -std=c++0x -o main ./main.cpp

Is RVO or NRVO the cause?

Upvotes: 0

Views: 165

Answers (2)

Clinton
Clinton

Reputation: 23145

RVO kicks in and elides the copy, and constructs GetPerson("X", 21) in place in p. Neither the copy constructor nor the move constructor needs to be called.

If you want to force a move here, then std::move(GetPerson("X", 21)) should do the trick, but I'm not sure why you'd want to.

Upvotes: 2

Ben Voigt
Ben Voigt

Reputation: 283941

Whether the move constructor is called or not is unimportant. What's important is that the COPY constructor is NOT called.

If your code relies on the move constructor being called here, it is broken, per [class.copy] p31.

Upvotes: 1

Related Questions