Должен ли конструктор перемещения принимать константную или неконстантную ссылку на rvalue?

В нескольких местах я видел рекомендуемые сигнатуры конструкторов копирования и перемещения, указанные как:

struct T
{
    T();
    T(const T& other);
    T(T&& other);
};

Где конструктор копирования принимает константную ссылку, а конструктор перемещения принимает неконстантное значение rvalue ссылка.

Однако, насколько я понимаю, это не позволяет мне использовать семантику перемещения при возврате константных объектов из функции, как в случае ниже:

T generate_t()
{
    const T t;
    return t;
}

Тестирование с помощью VC11 Beta, Tвызывается конструктор копирования, а не конструктор перемещения. Даже при использовании return std::move(t);конструктор копирования все равно вызывается.

Я вижу, как это имеет смысл, поскольку tявляется константой, поэтому не должно связываться с T&&. Использование const T&&в сигнатуре конструктора перемещения работает нормально и имеет смысл, но тогда у вас возникает проблема: поскольку otherявляется константой, вы не можете обнулить его члены, если они нужны для обнуления - это будет работать только тогда, когда все члены являются скалярами или имеют конструкторы перемещения с правильной подписью.

Похоже, что единственный способ убедиться, что конструктор перемещения вызывается в общем случае, сделать tнеконстантным в первую очередь, но мне не нравится делать это - константные вещи это хорошая форма, и я не ожидал, что клиент Tузнает, что ему пришлось пойти против этой формы, чтобы повысить производительность.

Итак, я думаю, мой вопрос двоякий; во-первых, должен ли конструктор перемещения принимать константную или неконстантную ссылку на rvalue? И второе: прав ли я в этой цепочке рассуждений? Что я должен перестать возвращать константные вещи?

33
задан Ben Hymers 26 May 2012 в 22:11
поделиться