Digamos que tengo las siguientes estructuras:
struct Foo
{
int val;
};
struct Test
{
Foo *bar;
};
y quería crear una Test
estructura:
Test get_test()
{
Test test;
Foo foo;
foo.val = 10;
test.bar = &foo;
cout << "INIT: " << test.bar->val << endl;
return test;
}
int main()
{
Test test = get_test();
cout << "AFTER: " << test.bar->val << endl;
return 0;
}
La salida es la siguiente:
INIT: 10
AFTER: 32723
He intentado hacer esto de manera diferente:
Test get_test()
{
Test test;
Foo *foo;
foo->val = 10;
test.bar = foo;
cout << "INIT: " << test.bar->val << endl;
return test;
}
Pero esto me dio una SIGSEGV (Address boundary error)
Desde mi limitada comprensión, creo que es debido a que en get_test()
foo
una variable temporal, por lo que la referencia no significa nada. ¿Cómo puedo hacer esto correctamente?
Estás en el camino correcto. En el primer ejemplo, una vez que get_test
regresa, foo
no existe más, y acceder a la dirección de donde estaba es un comportamiento indefinido. Lo mismo sucede en su segundo intento, pero aquí el problema es en get_test
sí mismo. Se declara Foo* foo;
, pero nunca lo asigna a cualquier cosa, lo que significa que la variable foo
se dirigen a alguna dirección aleatoria. Para acceder a él es un comportamiento indefinido. Tratar esto como su get_test
-función:
Test get_test()
{
Test test;
Foo *foo = new Foo();
foo->val = 10;
test.bar = foo;
cout << "INIT: " << test.bar->val << endl;
return test;
}
Aquí, asignamos foo
con new
, por lo que se le asigna en el montón, y permanecerá hasta que llame delete
en ella. Esto significa que necesita para asegurarse de que delete
una vez que haya terminado con él o usted tendrá una memoria de fugas. En C ++ 14, también puede hacerlo utilizando std::unique_ptr
:
struct Test
{
std::unique_ptr<Foo> bar;
};
{
Test test;
std::unique_ptr<Foo> foo = std::make_unique<Foo>();
foo->val = 10;
test.bar = std::move(foo);
cout << "INIT: " << test.bar->val << endl;
return test;
}
std::unique_ptr
se encargará de borrar foo
una vez que se sale del ámbito (cuando test
se destruye), y usted no tiene que preocuparse acerca de la memoria-fugas (pero no se puede copiar una std::unique_ptr
, por lo que tendrá a std::move
ella). std::unique_ptr
está disponible desde c ++ 11, std::make_unique
ya que c ++ 14. Usted también tendrá que #include <memory>
ser capaz de utilizarlas. Echa un vistazo a este enlace para obtener más información sobre la diferencia entre pila y pila, y éste para aprender más sobre std::unique_ptr
y mover la semántica.