Если посмотреть на get
, функция помощника для std::tuple
, вы заметите следующие перегрузки:Почему получить помощник станд :: возвратного кортеж RValue ссылки вместо значения
template< std::size_t I, class... Types >
constexpr std::tuple_element_t<I, tuple<Types...> >&&
get(tuple<Types...>&& t);
Другими словами, она возвращает ссылку rvalue, когда входной кортеж является самой ссылкой rvalue. Почему бы не вернуться по значению, вызвав move
в тело функции? Мой аргумент следующий: возврат get будет либо привязан к ссылке, либо значению (это может быть связано ни с чем, я полагаю, но это не должно быть обычным прецедентом). Если он привязан к значению, то в любом случае произойдет конструкция перемещения. Таким образом, вы ничего не теряете, возвращаясь по стоимости. Если вы привязываетесь к ссылке, то возврат ссылки rvalue может быть небезопасным. Для того, чтобы показать пример:
struct Hello {
Hello() {
std::cerr << "Constructed at : " << this << std::endl;
}
~Hello() {
std::cerr << "Destructed at : " << this << std::endl;
}
double m_double;
};
struct foo {
Hello m_hello;
Hello && get() && { return std::move(m_hello); }
};
int main() {
const Hello & x = foo().get();
std::cerr << x.m_double;
}
При запуске эта программа печатает:
Constructed at : 0x7ffc0e12cdc0
Destructed at : 0x7ffc0e12cdc0
0
Другими словами, х сразу зависшего ссылки. Если вы только что написали foo вот так:
struct foo {
Hello m_hello;
Hello get() && { return std::move(m_hello); }
};
Эта проблема не возникла. Кроме того, если вы затем использовать Foo так:
Hello x(foo().get());
Это не похоже, есть какие-либо дополнительные накладные расходы, вы возвращаете по значению или ссылки RValue. Я протестировал такой код, и кажется, что он будет последовательно выполнять только одну конструкцию движения. Например. если добавить элемент:
Hello(Hello &&) { std::cerr << "Moved" << std::endl; }
И я построить х, как указано выше, моя программа только печатает «Перемещенные» один раз, независимо от того, возвращать я по значению или ссылки RValue.
Есть ли веская причина, по которой мне не хватает, или это надзор?
Примечание: здесь есть хороший вопрос: Return value or rvalue reference?. Кажется, что возврат стоимости обычно предпочтительнее в этой ситуации, но тот факт, что он появляется в STL, заставляет меня любопытно, игнорирует ли STL это рассуждение, или если у них есть свои собственные собственные причины, которые могут быть не применимы в общем.
Редактировать: Кто-то предположил, что этот вопрос является дубликатом Is there any case where a return of a RValue Reference (&&) is useful?. Это не тот случай; этот ответ предполагает возвращение ссылкой rvalue как способ ускорить копирование данных. Как я подробно рассмотрю выше, копирование будет отменено, если вы вернетесь по ссылке value или rvalue, если вы сначала вызываете move
.
Это не удаленный дубликат. Мой ответ явно и подробно обсуждает, как возврат по значению и вызов std :: move заранее достигает такого же эффекта перехода от элемента данных. Мой вопрос связан с различиями в двух подходах. Вопрос, который я цитировал, более связан с моим вопросом, чем тот, который вы указали. Пожалуйста, внимательно прочитайте, прежде чем спешить, чтобы наклеить что-то дублирующее. –
, если вы вернетесь по значению - вы создаете копию. если вы переместите его, вы переместите копию. если вы вернете ссылку на r-значение, вы можете либо переместить ее, то исходный объект будет перемещен или не будет иметь дело с семантикой перемещения, тогда он будет вести себя как обычная ссылка. Дело в том, что если вы вернете ссылку на r-значение, вы не будете принудительно копировать. –
Зачем нужна конструкция конструкции? – Columbo