4

I have the following class:

class Student
{
private:
    std::string firstName;
    std::string lastName;
public:
    Student():firstName(""), lastName("") 
    { 
    }

    Student(const std::string &first, const std::string &last)
        :firstName(first), lastName(last) 
    {
    }

    Student(const Student &student)
        :firstName(student.firstName), lastName(student.lastName)
    {
    }

    Student(Student &&student)
    {
        firstName=std::move(student.firstName);
        lastName=std::move(student.lastName);
    }

    // ... getters and setters    
};

I use it like this:

std::vector<std::shared_ptr<Student>> students;
std::shared_ptr<Student> stud1 = std::make_shared<Student>("fn1","ln1");
students.push_back(stud1);
Student stud2("fn2","ln2");
students.push_back(std::make_shared<Student>(std::move(stud2)));

From what I have read, the move constructor in automatically generated by the compiler. Right now, when I step into this line students.push_back(std::make_shared<Student>(std::move(stud2))); I reach the move constructor, which is ok.

If I comment out the move constructor when I step into that line I reach the copy constructor. I don't understand why this is happening.

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Jack Willson
  • 2,094
  • 6
  • 21
  • 23
  • IIRC, the compiler automatically generates copy constructors. Move constructors are not automatically generated. – Matt Kline Jan 20 '13 at 16:37
  • 1
    move constructors are only automatically generated under certain conditions: http://stackoverflow.com/questions/4943958/c-conditions-for-automatic-generation-of-default-ctor-copy-ctor-and-default – Nate Kohl Jan 20 '13 at 16:38
  • (I'm curious why you don't use initializer list in your move constructor.) – Mat Jan 20 '13 at 16:38
  • I am sorry Mat, but don't know what do you mean, i am new to c++ – Jack Willson Jan 20 '13 at 16:52
  • Thanks you nate and also slavik , please add your comment as a response so i can accept it. – Jack Willson Jan 20 '13 at 16:55
  • 1
    You're using `Student(...) : firstName(...) {}` syntax everywhere except in your move constructor. That's strange. You could use it there too and potentially save two string constructions. – Mat Jan 20 '13 at 17:04
  • @ildjarn Aren't the tags "visual=c++" (or "visual-studio-2012") and "c++11" mutually exclusive (in particular in the context of this question)? – Walter Jan 21 '13 at 09:56
  • @Walter No, since the `visual-studio-2012` tag makes the answer to this question obviously trivial. But you're right in that this bit of information would have helped greatly with answering. Other than that I don't see how the `visual-c++` and `c++11` tags could be mutually exclusive, considering the many C++11 features this compiler supports in its current version, especially move-semantics to a large part (though its indeed a bit unlucky for the question that it doesn't support this part of the move-semantics feature)... – Christian Rau Jan 21 '13 at 10:18
  • @Walter ...Neither would I regard `gcc` and `C++11` mutually exclusive just because the former doesn't support the inheriting constructors feature of the latter. Though seeing that your comment was surely not meant that seriously, I have to agree with you (especially since this lack of move-semantics is totally bugging me too, who cares about variadic templates, just don't make me write those damn trivial move members) ;) – Christian Rau Jan 21 '13 at 10:20

2 Answers2

3

Visual C++ 2012 does not implicitly generate move constructors or move assignment operators.

(The rules governing when move operations are and are not implicitly declared and defined changed several times during standardization; Visual C++ 2012 does not support the standardized (2011) set of rules.)

Walter
  • 44,150
  • 20
  • 113
  • 196
James McNellis
  • 348,265
  • 75
  • 913
  • 977
1

In your case, you may simple declare all these constructors =default, e.g.

class student
{
  std::string firstname, surname;
public:
  student(student const&) = default;
  student(student&&) = default;
  student&operator=(student const&) = default;
  student&operator=(student&&) = default;
  // etc
};

and don't worry about the details: the compiler should sort this out and generate the appropriate call to std::string::string(string&&) (move constructor).

EDIT Of course, this will not work with deficient compilers, but if you're tagging "C++11", then you should expect a C++11 answer.

Walter
  • 44,150
  • 20
  • 113
  • 196