Вы на правильном пути. В вашем первом примере, когда get_test
вернется, foo
больше не будет существовать, и доступ к адресу, на котором он находился, является неопределенным поведением. То же самое происходит во второй попытке, но здесь проблема в самом get_test
. Вы объявляете Foo* foo;
, но никогда не назначаете его чему-либо, что означает, что переменная foo
указывает на некоторый случайный адрес. Доступ к нему - неопределенное поведение. Попробуйте это как вашу get_test
-функцию:
Test get_test()
{
Test test;
Foo *foo = new Foo();
foo->val = 10;
test.bar = foo;
cout << "INIT: " << test.bar->val << endl;
return test;
}
Здесь мы выделяем foo
с new
, так что она выделяется в куче и будет оставаться до тех пор, пока вы не вызовете delete
для нее , Это означает, что вы должны убедиться, что delete
это, как только вы закончите с этим, иначе у вас будет утечка памяти. В C ++ 14 вы также можете сделать это, используя 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
позаботится об удалении foo
, как только он выйдет из области видимости (когда test
уничтожен), и вам не нужно беспокоиться об утечках памяти (но вы не можете скопировать std::unique_ptr
, поэтому вам придется std::move
его). std::unique_ptr
доступно с c ++ 11, std::make_unique
с c ++ 14. Вам также нужно будет #include <memory>
, чтобы иметь возможность их использовать. Проверьте эту ссылку , чтобы узнать больше о разнице между кучей и стеком, и эту , чтобы узнать больше о std::unique_ptr
и семантике перемещения.