Czy zwracanie przez rvalue reference jest bardziej efektywne?

Na przykład:

Beta_ab&&
Beta::toAB() const {
    return move(Beta_ab(1, 1));
}
Author: Johannes Schaub - litb, 2009-07-12

2 answers

Beta_ab&&
Beta::toAB() const {
    return move(Beta_ab(1, 1));
}

Zwraca zwisające odniesienie, podobnie jak w przypadku przypadku odniesienia lvalue. Po powrocie funkcji obiekt tymczasowy zostanie zniszczony. Powinieneś zwrócić Beta_ab według wartości, jak poniżej

Beta_ab
Beta::toAB() const {
    return Beta_ab(1, 1);
}

Teraz poprawnie przenosi tymczasowy obiekt Beta_ab do wartości zwracanej funkcji. Jeśli kompilator może, całkowicie uniknie tego ruchu, używając RVO (return value optimization). Teraz możesz wykonać następujące czynności

Beta_ab ab = others.toAB();

And it will move należy utworzyć tymczasowe w ab, lub zrobić RVO, aby całkowicie pominąć wykonywanie ruchu lub kopiowania. Polecam przeczytać Boostcon09 rvalue referuje 101, który wyjaśnia sprawę i jak (N)RVO oddziałuje z tym.


Twój przypadek zwrócenia referencji rvalue byłby dobrym pomysłem przy innych okazjach. Wyobraź sobie, że masz getAB() funkcję, którą często wywołujesz na tymczasowej. Nie jest optymalne, aby zwracało odniesienie const lvalue dla rvalue temporary. Możesz zaimplementuj to w ten sposób

struct Beta {
  Beta_ab ab;
  Beta_ab const& getAB() const& { return ab; }
  Beta_ab && getAB() && { return move(ab); }
};

Zauważ, że move w tym przypadku nie jest opcjonalne, ponieważ ab nie jest ani lokalną automatyczną, ani tymczasową wartością r. ref-kwalifikator && mówi, że druga funkcja jest wywoływana na rvalue temporary, wykonując następujący ruch, zamiast copy

Beta_ab ab = Beta().getAB();
 185
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-12 20:28:10

To Może być bardziej efektywne, na przykład w nieco innym kontekście:

template <typename T>
T&& min_(T&& a, T &&b) {
    return std::move(a < b? a: b);
}

int main() {
   const std::string s = min_(std::string("A"), std::string("B"));
   fprintf(stderr, "min: %s\n", s.c_str());
   return 0;
}

Jako ciekawostkę, na mojej maszynie clang++ -O3 generuje 54 instrukcje dla kodu powyżej w porównaniu do 62 instrukcji dla zwykłego std::min. Jednak z -O0 generuje 518 instrukcji dla kodu powyżej, a 481 dla zwykłego std::min.

 0
Author: wonder.mice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-09 17:15:09