Ви повинні повернути за значенням.
Стандарт має специфічну особливість для підвищення ефективності повернення за вартістю. Це називається "копіювати елізію", а конкретніше в даному випадку "названа оптимізація повернутого значення (NRVO)".
Компіляторам не потрібно його реалізовувати, але знову ж таки компіляторам не потрібно реалізовувати функції вбудовування (або взагалі проводити оптимізацію). Але продуктивність стандартних бібліотек може бути досить поганою, якщо компілятори не оптимізують, і всі серйозні компілятори реалізують вбудовані лінії та NRVO (та інші оптимізації).
Коли застосовується NRVO, копіювання в такий код не буде:
std::vector<int> f() {
std::vector<int> result;
... populate the vector ...
return result;
}
std::vector<int> myvec = f();
Але користувач може захотіти зробити це:
std::vector<int> myvec;
... some time later ...
myvec = f();
Copy elision не заважає копіювати тут, оскільки це призначення, а не ініціалізація. Однак вам все одно варто повернутись за вартістю. У C ++ 11 призначення оптимізоване чимсь іншим, що називається "семантика переміщення". У C ++ 03 наведений вище код дійсно викликає копію, і хоча теоретично оптимізатор міг би його уникнути, на практиці це занадто складно. Отже, замість myvec = f()
C ++ 03 ви повинні написати це:
std::vector<int> myvec;
... some time later ...
f().swap(myvec);
Існує ще один варіант - запропонувати користувачеві більш гнучкий інтерфейс:
template <typename OutputIterator> void f(OutputIterator it) {
... write elements to the iterator like this ...
*it++ = 0;
*it++ = 1;
}
Потім ви також можете підтримати існуючий векторний інтерфейс:
std::vector<int> f() {
std::vector<int> result;
f(std::back_inserter(result));
return result;
}
Це може бути менш ефективним, ніж ваш існуючий код, якщо ваш існуючий код використовує reserve()
більш складний спосіб, ніж просто фіксована сума. Але якщо ваш існуючий код в основному push_back
повторно звертається до вектора, тоді цей код на основі шаблону повинен бути таким же хорошим.
f
?