#c
#c
Вопрос:
Я немного смущен следующим кодом
void foo() {
std::list<A*> list;
for (int i = 0; i < 3; i ) {
A a = A(i);
list.push_back(amp;a);
}
for (Iterator it = list.begin(); it != list.end(); it ) {
std::cout << (*it);
}
}
который трижды выводит объект a с аргументом конструктора 2, то есть последний объект, созданный в цикле.
Что я здесь делаю не так?
Комментарии:
1. Это не то, как вы включаетесь в список. Даже если бы это было так — вы отправляете ссылки на объекты, которые не будут существовать вне первой итерации цикла
2. @Leeor извините, это была опечатка
3. Вторая часть все еще применяется — вы запускаете один и тот же объект с каждой итерацией, так что у вас есть хороший шанс увидеть последнее значение (и что 3 указателя будут одинаковыми), но не доверяйте неопределенному поведению
4. @Leeor исходя из java, я всегда попадаю в эту ловушку
Ответ №1:
У вас есть список висячих указателей.
for (int i = 0; i < 3; i ) {
A a = A(i);
list(amp;a);
}
На каждой итерации этот цикл создает объект типа A
, который немедленно уничтожается по завершении итерации. Таким образом, содержимое списка не определено. Вам понадобится что-то вроде этого:
for (int i = 0; i < 3; i ) {
A* a = new A(i);
list(a);
}
…но не забудьте удалить их все в другом цикле, когда закончите со списком.
Комментарии:
1. Или используйте
std::shared_ptr<A>
илиstd::unique_ptr<A>
вместо необработанного указателя.
Ответ №2:
Переменная a
является локальной для первого цикла for , поэтому она уничтожается в конце каждой итерации цикла. Это означает, что после завершения цикла все три указателя list
указывают на объекты, которые больше не существуют. Разыменование этих указателей приводит к неопределенному поведению.
Ответ №3:
Если вы хотите меньше беспокоиться о том, чтобы не забывать выделять выделенную память (и иметь более приятный код, менее подверженный ошибкам), вам следует использовать unique_ptr
or shared_ptr
(прочитайте о них и выберите тот, который лучше всего соответствует вашим потребностям).
Вот небольшой пример (обратите внимание, как элементы в векторе удаляются, когда вектор выходит за пределы области видимости):
cout<<"Scope begins"<<endl;
{
vector< unique_ptr<A> > v;
for (int i=0; i<5; i){
v.push_back(unique_ptr<A>(new A(i)) );
}
}
cout<<"Scope ends"<<endl;
Живая демонстрация здесь.