Considere este código. He visto este tipo de código varias veces. words
es un vector local. ¿Cómo es posible devolverlo desde una función?
¿Podemos garantizar que no morirá?
std::vector<std::string> read_file(const std::string& path)
{
std::ifstream file("E:\\names.txt");
if (!file.is_open())
{
std::cerr << "Unable to open file" << "\n";
std::exit(-1);
}
std::vector<string> words;//this vector will be returned
std::string token;
while (std::getline(file, token, ','))
{
words.push_back(token);
}
return words;
}
std::vector<std::string>&
Respuestas:
Siempre que no se devuelva ninguna referencia, está perfectamente bien hacerlo.
words
se moverá a la variable que recibe el resultado.La variable local quedará fuera de alcance. después de que fue movido (o copiado).
fuente
Pre C ++ 11:
La función no devolverá la variable local, sino una copia de ella. Sin embargo, su compilador podría realizar una optimización donde no se realiza ninguna acción de copia real.
Consulte esta pregunta y respuesta para obtener más detalles.
C ++ 11:
La función moverá el valor. Consulte esta respuesta para obtener más detalles.
fuente
Creo que se está refiriendo al problema en C (y C ++) de que no se permite devolver una matriz desde una función (o al menos no funcionará como se esperaba); esto se debe a que la matriz devolverá (si la escribe en la forma simple) devuelve un puntero a la matriz real en la pila, que luego se elimina rápidamente cuando regresa la función.
Pero en este caso, funciona, porque
std::vector
es una clase, y las clases, como las estructuras, pueden (y serán) copiadas al contexto de los llamadores. [En realidad, la mayoría de los compiladores optimizarán este tipo particular de copia usando algo llamado "Optimización del valor de retorno", específicamente introducido para evitar copiar objetos grandes cuando son devueltos desde una función, pero eso es una optimización, y desde la perspectiva de los programadores, lo hará comportarse como si el constructor de asignaciones fuera llamado para el objeto]Siempre que no devuelva un puntero o una referencia a algo que está dentro de la función que regresa, está bien.
fuente
Para comprender bien el comportamiento, puede ejecutar este código:
El resultado es el siguiente:
Tenga en cuenta que este ejemplo se proporcionó en el contexto de C ++ 03, podría mejorarse para C ++> = 11
fuente
No estoy de acuerdo y no recomiendo devolver un
vector
:Esto es mucho más rápido:
Probé en Visual Studio 2017 con los siguientes resultados en modo de lanzamiento:
8.01 MOP por referencia
5.09 MOP que regresa vector
En el modo de depuración, las cosas son mucho peores:
0,053 MOPS por referencia
0,034 MOP por vector de retorno
fuente
En realidad, esto es un error de diseño. No debería utilizar un valor de retorno para nada que no sea un primitivo para algo que no sea relativamente trivial.
La solución ideal debe implementarse mediante un parámetro de retorno con una decisión sobre la referencia / puntero y el uso adecuado de una "const \ 'y \' ness" como descriptor.
Además de esto, debe darse cuenta de que la etiqueta en una matriz en C y C ++ es efectivamente un puntero y su suscripción es efectivamente un desplazamiento o un símbolo de adición.
Así que la etiqueta o ptr array_ptr === array label que devuelve foo [offset] en realidad dice que el elemento de retorno en la ubicación del puntero de memoria foo + offset del tipo tipo de retorno.
fuente