Você deve retornar por valor.
O padrão possui uma característica específica para melhorar a eficiência do retorno por valor. É chamado de "elisão de cópia" e, mais especificamente, neste caso, a "otimização do valor de retorno nomeado (NRVO)".
Os compiladores não precisam implementá-lo, mas, novamente, os compiladores não precisam implementar o inlining de funções (ou realizar qualquer otimização). Mas o desempenho das bibliotecas padrão pode ser muito pobre se os compiladores não otimizam, e todos os compiladores sérios implementam inlining e NRVO (e outras otimizações).
Quando o NRVO for aplicado, não haverá cópia no seguinte código:
std::vector<int> f() {
std::vector<int> result;
... populate the vector ...
return result;
}
std::vector<int> myvec = f();
Mas o usuário pode querer fazer isso:
std::vector<int> myvec;
... some time later ...
myvec = f();
A elisão de cópia não impede uma cópia aqui porque é uma atribuição em vez de uma inicialização. No entanto, você ainda deve retornar por valor. Em C ++ 11, a atribuição é otimizada por algo diferente, chamado "mover semântica". Em C ++ 03, o código acima causa uma cópia e, embora em teoria um otimizador possa evitá-lo, na prática é muito difícil. Então myvec = f()
, em vez de , em C ++ 03, você deve escrever isto:
std::vector<int> myvec;
... some time later ...
f().swap(myvec);
Existe outra opção, que é oferecer uma interface mais flexível ao usuário:
template <typename OutputIterator> void f(OutputIterator it) {
... write elements to the iterator like this ...
*it++ = 0;
*it++ = 1;
}
Você também pode oferecer suporte à interface baseada em vetor existente além disso:
std::vector<int> f() {
std::vector<int> result;
f(std::back_inserter(result));
return result;
}
Isso pode ser menos eficiente do que seu código existente, se seu código existente usar reserve()
de uma forma mais complexa do que apenas uma quantia fixa inicial. Mas se o seu código existente basicamente chamar push_back
o vetor repetidamente, esse código baseado em modelo deve ser tão bom.
f
?