Нужно ли определять конструкторы перемещения из разных классов? - PullRequest
11 голосов
/ 29 января 2011

Рассмотрим следующее:

struct X
{
    Y y_;

    X(const Y & y) :y_(y) {}    
    X(Y && y) :y_(std::move(y)) {}
};

Необходимо ли определять конструктор наподобие второго, чтобы в полной мере использовать семантику перемещения? Или об этом позаботятся автоматически в соответствующих ситуациях?

Ответы [ 2 ]

7 голосов
/ 30 января 2011

Да, но нет. Ваш код должен быть таким:

struct X
{
    Y y_;

    X(Y y) : // either copy, move, or elide a Y
    y_(std::move(y)) // and move it to the member
    {} 
};

Если вы когда-нибудь скажете в дизайне «Мне нужна моя собственная копия этих данных» *, тогда вам просто нужно взять аргумент по значению и переместить его туда, где он должен быть. Ваша задача - решить, как создать это значение, это зависит от доступных конструкторов для этого значения, поэтому пусть он сделает этот выбор, каким бы он ни был, и будет работать с конечным результатом.

* Это относится и к функциям, конечно, например:

void add_to_map(std::string x, int y) // either copy, move or elide a std::string
{
    // and move it to where it needs to be
    someMap.insert(std::make_pair(std::move(x), y));
}

Обратите внимание, что применяется в C ++ 03, в некоторой степени, если тип был по умолчанию конструируемым и заменяемым (который все равно перемещается):

// C++03
struct X
{
    std::string y_;

    X(std::string y) // either copy or elide a std::string
    {
        swap(y_, y); // and "move" it to the member
    } 
};

Хотя это и не так широко распространено.

1 голос
/ 29 января 2011

Да, это необходимо. Const ref может быть только копией, а не ходом.

...