c++ - valores - ¿Por qué está bien devolver el vector de la función?
una funcion puede devolver mas de un valor en c (5)
Considere este código, he visto este tipo de código varias veces, las words
son vector local, cómo es posible regresar de la función. ¿Podemos garantizar que no va a 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;
}
¿Podemos garantizar que no va a morir?
Mientras no se devuelva ninguna referencia, está perfectamente bien hacerlo. words
se moverán a la variable que recibe el resultado.
La variable local saldrá del alcance. después de que fue movido (o copiado).
Pre C ++ 11:
La función no devolverá la variable local, sino una copia de la misma. Sin embargo, su compilador podría realizar una optimización donde no se realiza una acción de copia real.
Vea esta pregunta y respuesta para más detalles
C ++ 11:
La función moverá el valor, mira esta respuesta para más detalles
Creo que te estás refiriendo al problema en C (y C ++) que no está permitido devolver una matriz desde una función (o al menos no funcionará como se esperaba), esto es porque la matriz regresará (si la escribes en la forma simple) devuelve un puntero a la matriz real en la pila, que luego se elimina rápidamente cuando la función regresa.
Pero en este caso, funciona, porque std::vector
es una clase, y las clases, al igual que las estructuras, se pueden copiar (y se copiarán) en el contexto de las personas que llaman. [En realidad, la mayoría de los compiladores optimizarán este tipo particular de copia utilizando algo llamado "Optimización del valor de retorno", introducido específicamente para evitar la copia de objetos grandes cuando se devuelven de una función, pero eso es una optimización, y desde la perspectiva de los programadores, comportarse como si el constructor de la asignación se llama para el objeto]
Siempre y cuando no devuelva un puntero o una referencia a algo que esté dentro de la función de retorno, usted está bien.
Esto es realmente una falla de diseño, no debería usar un valor de retorno para nada que no sea primitivo para algo que no sea relativamente trivial. La solución ideal debe implementarse a través de un parámetro de retorno con una decisión sobre referencia / ptr y el uso adecuado de un "const / ''y /' ness" como descriptor.
Además de esto, debe tener en cuenta que la etiqueta de una matriz en C y C ++ es efectivamente un puntero y su suscripción es efectivamente un desplazamiento o un símbolo de suma.
Entonces, la etiqueta o la matriz ptr array_ptr === etiqueta de matriz que devuelve foo [offset] realmente está diciendo elemento de retorno en la memoria ptr location foo + offset de tipo type return.
Para comprender bien el comportamiento, puede ejecutar este código:
#include <iostream>
class MyClass
{
public:
MyClass() { std::cout << "run constructor MyClass::MyClass()" << std::endl; }
~MyClass() { std::cout << "run destructor MyClass::~MyClass()" << std::endl; }
MyClass(const MyClass& x) { std::cout << "run copy constructor MyClass::MyClass(const MyClass&)" << std::endl; }
MyClass& operator = (const MyClass& x) { std::cout << "run assignation MyClass::operator=(const MyClass&)" << std::endl; }
};
MyClass my_function()
{
std::cout << "run my_function()" << std::endl;
MyClass a;
std::cout << "my_function is going to return a..." << std::endl;
return a;
}
int main(int argc, char** argv)
{
MyClass b = my_function();
MyClass c;
c = my_function();
return 0;
}
El resultado es el siguiente:
run my_function()
run constructor MyClass::MyClass()
my_function is going to return a...
run constructor MyClass::MyClass()
run my_function()
run constructor MyClass::MyClass()
my_function is going to return a...
run assignation MyClass::operator=(const MyClass&)
run destructor MyClass::~MyClass()
run destructor MyClass::~MyClass()
run destructor MyClass::~MyClass()