Мой вопрос касается идеальной пересылки, давайте сначала посмотрим на пример,
template<typename A, typename B>
void foo(A &&a, B &&b) {
A internal_a = std::forward<A>(a);
B internal_b = std::forward<B>(b);
}
Пока все хорошо. Я могу назвать это так,
X x;
Y y;
// do a lot of stuff on x, y
//.....
//.....
// we will use x,y in foo(x, y) only, so we can just move
foo(std::move(x), std::move(y));
Теперь, скажем, foo может потерпеть неудачу.
template<typename A, typename B>
bool foo(A &&a, B &&b) {
A internal_a = std::forward<A>(a);
B internal_b = std::forward<B>(b);
// ...
if (xxx) {
return false;
}
// ...
return true;
}
В звонящем
X x;
Y y;
// do a lot of stuff on x, y
//.....
//.....
// Oh my!
while (!foo(std::move(x), std::move(y)) ;
Это не сработает, потому что первый вызов foo переместит x и y.
Если вызывающая сторона не использует перемещение, то мы теряем все преимущества перемещения.
Мы можем сделать это:
X x;
Y y;
do {
// do a lot of stuff on x, y
//.....
//.....
}
while (!foo(std::move(x), std::move(y)) ;
Это делает вызывающего абонента очень проблематичным.
Мы также можем сделать это,
template<typename A, typename B>
bool foo(A &&a, B &&b) {
A internal_a = std::forward<A>(a);
B internal_b = std::forward<B>(b);
// ...
if (xxx) {
// This may move or copy, where the copy is uncessary
a = std::forward<A>(internal_a);
b = std::forward<B>(internal_b);
return false;
}
// ...
return true;
}
Это может хорошо сработать, если оно действительно перемещается в вызывающей стороне. Если звонящий не двигается, это включает ненужные копии.
Вероятно, мне нужно точно знать, что перемещение или копирование происходят внутри идеальной пересылки, и если это перемещение, мы должны переместить заднюю часть, чтобы сделать звонящего легче.
Пожалуйста, сообщите. Спасибо.