Powinieneś zwrócić według wartości.
Standard ma specyficzną funkcję poprawiającą efektywność zwrotu wartości. Nazywa się to „elizją kopiowania”, a dokładniej w tym przypadku „nazwaną optymalizacją wartości zwracanej (NRVO)”.
Kompilatory nie muszą tego implementować, ale z drugiej strony kompilatory nie muszą implementować funkcji inlining (ani w ogóle wykonywać jakiejkolwiek optymalizacji). Ale wydajność standardowych bibliotek może być dość słaba, jeśli kompilatory nie optymalizują, a wszystkie poważne kompilatory implementują inlining i NRVO (i inne optymalizacje).
Po zastosowaniu NRVO nie będzie kopiowania w następującym kodzie:
std::vector<int> f() {
std::vector<int> result;
... populate the vector ...
return result;
}
std::vector<int> myvec = f();
Ale użytkownik może chcieć to zrobić:
std::vector<int> myvec;
... some time later ...
myvec = f();
Opcja Copy Elision nie zapobiega tutaj kopiowaniu, ponieważ jest to raczej przypisanie niż inicjalizacja. Jednak nadal powinieneś zwracać według wartości. W C ++ 11 przypisanie jest optymalizowane przez coś innego, zwanego „semantyką ruchu”. W C ++ 03 powyższy kod powoduje kopiowanie i chociaż teoretycznie optymalizator mógłby tego uniknąć, w praktyce jest to zbyt trudne. Więc zamiast tego myvec = f()
w C ++ 03 powinieneś napisać to:
std::vector<int> myvec;
... some time later ...
f().swap(myvec);
Jest jeszcze jedna opcja, która ma zaoferować użytkownikowi bardziej elastyczny interfejs:
template <typename OutputIterator> void f(OutputIterator it) {
... write elements to the iterator like this ...
*it++ = 0;
*it++ = 1;
}
Następnie możesz również obsługiwać istniejący interfejs oparty na wektorach:
std::vector<int> f() {
std::vector<int> result;
f(std::back_inserter(result));
return result;
}
Może to być mniej wydajne niż istniejący kod, jeśli istniejący kod używa reserve()
w sposób bardziej złożony niż tylko ustalona z góry kwota. Ale jeśli twój istniejący kod w zasadzie push_back
wielokrotnie odwołuje się do wektora, to ten oparty na szablonie kod powinien być równie dobry.
f
?