Re[3]: std::vector. как правильно упаковать в вектор объект
От: Alex_Avr Россия  
Дата: 05.09.06 08:23
Оценка:
Здравствуйте, __GnoM, Вы писали:

А>>[ccode]

А>>>class A
А>>>{
А>>> public:
А>>> A();
А>>> ~A();
А>>> BOOL Init();
А>>> BOOL Start();
А>>> .
А>>> .
А>>> .
А>>> private:
А>>> vector<B> vec; Элементы вектора хранятся по значению
А>>>};

А>>>A::~A()

А>>>{
А>>А> vector<B>::iterator iter = vec.begin(); // Этот код не может не падать. ВЕКТОР УДАЛИТ ЭЛЕМЕНТЫ САМ.
А>>> while(iter != vec.end())
А>>> {
А>>> delete iter;
А>>> iter++;
А>>> }

А>>>}

__G>Можно уточнить, вектор удалит элементы сам путём вызова деструктора ~B() или как???

__G>Просто если в B имеет место динамическое выделение памяти, необходимо гарантировать её стопоцентное освобождение???

__G>Да и вопрос остался. Падает только на втором элементе вектора, первый успешно удаляется!


В vec элементы хранятся по значению, т.е. вектор сам их создает и уничтожает.
Поэтому руками удалять их _нельзя_, и этот while _нужно_ убрать. Иначе ошибка
будет возникать в деструкторе класса vector.

В вышепреведенном коде происходит следующее.
В векторе данные хранятся непрерывно одним блоком памяти. В используемой вами STL итератор
определен как указатель (в STLPort в отладочном режиме это не так, поэтому этот код c STLPort даже бы не скомпилировался).

В данном случае интератор, указывающий на начальный элемент вектора — это просто указатель
на блок памяти, выделенный классом vector. Поэтому первое удаление происходит нормально (да и то,
у других компиляторов здесь могла возникнуть ошибка из-за выделения по new[], а удалению по delete).
На следующей итерации итератор-указатель указывает на следующий элемент вектора, т.е. адрес
который находился внутри уже удаленного блока памяти.

Таким образом получается, что производится попытка освобождения памяти, начиная с адреса, с которого
не выделялся ни один из блоков памяти, не говоря уже о том, что удаление блока памяти,
куда входил этот элемент вектора, уже произошло.

В результате — повреждение кучи с перспективой искать причины странных и непостоянно проявляющихся ошибок.
Можно сказать, что в данном случае вам еще повезло, что ошибка сразу возникает.

Так что либо в приведенном коде опечатки, либо автор кода не представляет,
что из себя представляет шаблонный класс вектора и как его можно использовать.

__G>Данный метод — это просто пример для обсуждения, в реально используемом классе нужно было гарантировать правильное создание объекта и инициализацию его параметров, поэтому создаётся динамически. Неудобно, но другого варинта не нашлось, пока....


Тогда лучше описать, какую задачу решаете по созданию объекта, может кто и лучше чего посоветует.
С уважением, Александр Авраменко.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.