问题
Suppose I have the following two classes:
class Person
{
public:
Person(string name, string surname)
: _name(move(name)), _surname(move(surname)) { }
...
private:
string _name;
string _surname;
};
class Student : public Person
{
public:
Student(string name, string surname, Schedule schedule)
: Person(move(name), move(surname)), _schedule(move(schedule)) { }
...
private:
Schedule _schedule;
};
int main()
{
Student s("Test", "Subject", Schedule(...));
...
return 0;
}
Is that a good usage of move semantics? As you can see there's a layer of 'move-s' in the Student constructor. Is it possible to avoid the move
function call overhead without using const
references to forward the parameters to the base constructor?
Or perhaps..should I be using const references whenever I need to forward parameters to the base constructor?
回答1:
No. You will only get a performance improvement for types which are of a very large size, which is very rare. Absolutely, when dealing with some type which you don't know in advance is very expensive to move, or immovable, then assume cheap moves.
Your existing code is idiomatic C++11, and a perfect forwarding constructor in this respect is wrong and will hideously break things for one parameter to boot.
回答2:
Consider favoring code readability and simplicity before choosing to optimize. It is quite likely that you do not really need to save on one copy/move operation, in which case you should favor clarity and simplicity (e.g. take by reference to const
).
This said, if you are concerned about the overhead of forwarding your constructor's arguments, you can make your constructor a constructor template and use perfect forwarding to incur minimum overhead no matter whether you are passing an rvalue or an lvalue:
class Person
{
public:
template<typename T, typename U>
Person(T&& name, U&& surname)
: _name(std::forward<T>(name)), _surname(std::forward<U>(surname)) { }
...
private:
string _name;
string _surname;
};
class Student : public Person
{
public:
template<typename T, typename U, typename V>
Student(T&& name, U&& surname, V&& schedule)
: Person(
std::forward<T>(name),
std::forward<U>(surname)),
_schedule(std::forward<V>(schedule))
{ }
...
private:
Schedule _schedule;
};
来源:https://stackoverflow.com/questions/15449397/should-move-semantics-be-used-in-constructor-chains