• Познакомьтесь с пентестом веб-приложений на практике в нашем новом бесплатном курсе

    «Анализ защищенности веб-приложений»

    🔥 Записаться бесплатно!

  • CTF с учебными материалами Codeby Games

    Обучение кибербезопасности в игровой форме. Более 200 заданий по Active Directory, OSINT, PWN, Веб, Стеганографии, Реверс-инжинирингу, Форензике и Криптографии. Школа CTF с бесплатными курсами по всем категориям.

Vector при добавлении нового элемента удаляет старый

  • Автор темы Monarh
  • Дата начала
M

Monarh

Не могу разобраться зачем он так поступает :(

Имеется 2 класса:

Код:
class Cls_A
{
char* CA_Format;
void* VPtr_Array;
Cls_A();
void* Allocation( string& Format ); // В соответствии с содержимым строки Format выделяет память под CA_Format и VPtr_Array;
void DeAllocation();
~Cls_A();
}

Cls_A::Cls_A()
{
CA_Format = NULL;
VPtr_Array = NULL;
}

void Cls_A::DeAllocation()
{
if( CA_Dimensions_Info != NULL )
{
delete[] CA_Dimensions_Info;
CA_Dimensions_Info = NULL;
}

if( VPtr_Array != NULL )
{
delete[] (char*)VPtr_Array;
VPtr_Array = NULL;
}
}

Cls_A::~Cls_A()
{
DeAllocation();
}
Код:
class Cls_B
{
...
vector<Cls_A> VecCls_A;
void* Allocation();
...
}

void* Cls_B::Allocation()
{
...
Cls_A* ClsPtr_A = NULL;
ClsPtr_A = new Cls_A;
...

void* VPtr_Array;
(1)	VPtr_Array = ClsPtr_A -> Allocation( Str_Format );

// Вставляем вновь созданный Массив в найденную позицию Place_for_Insert.
(2)	VecCls_A.insert( Place_for_Insert( VPtr_Array ), (*ClsPtr_A) );
...
}

При добавлении, первый раз, класса Cls_A в функции Cls_B::Allocation()
на стадии (1) выделяется память нормально.
на стадии (2) добавляется в вектор нормально.

При добавлении, второй раз, класса Cls_A в функции Cls_B::Allocation()
на стадии (1) выделяется память нормально.
на стадии (2) программа заползает в деструктор первого объекта и всю память чистит и только после этого, со спокойной душой, добавляет второй объект.
Хотя первый объект почищен vector.size() == 2 и вроде как указатели указывают на теже адреса, но по тем же адресам уже совсем не то, что надо.
И на последующем шаге при обращении к первому объекту программа завершает работу с ошибкой.

Подскажите пожалуйста что не так делаю и как надо.
Заранее всем большое спасибо !!!
 
E

European

По этим обрывкам кода ничего понять невозможно
 
M

Monarh

Я уже вроде разобрался.

Это происходит из-за того, что vector при добавлении нового элемента удаляет все имеющиеся, предварительно создав их копии.
То есть, в моём примере, поскольку, VecCls_A - это вектор объектов класса Cls_A, то при добавлении нового элемента он создаёт копии
каждого объекта и затем вызывает деструктор каждого из имеющихся в векторе объектов, чтобы затем их заменить созданными копиями.
А поскольку в объекте класса Cls_A два указателя, то при копировании копируются только указатели, в то время как при удалении объекта
удаляются сами массивы на которые указывают эти указатели.

Выхода, как минимум, два:
1) написать конструктор копирования, но в моём случае он мне без надобности.
2) переопределить вектор VecCls_A, как вектор указателей на объекты класса.

Хотел сделать вектор VecCls_A, как вектор ссылок на объекты класса, но похоже так нельзя.
Если можно подскажите как.
Я так понял ссылки при определении должны сразу быть проинициализированы и потому нельзя определить вектор ссылок ???

Если что-то в моих предположения неверно, то поправьте.
Заранее всем большое спасибо.
 
E

European

Это происходит из-за того, что vector при добавлении нового элемента удаляет все имеющиеся, предварительно создав их копии.
Не совсем так. Вектор хранит свои элементы в непрерывной области памяти. Если при добавлении элемента не хватает выделенной памяти, то вектор осуществляет копирование элементов в бОльшую область память. Управлять размером области памяти можно при помощи метода reserve()
Выхода, как минимум, два:
1) написать конструктор копирования, но в моём случае он мне без надобности.
Хорошим тоном программирования для объектов, содержащих выделенную динамическую память, является или реализация пары оператор присваивания + конструктор копирования или их закрытие
 
M

Monarh

Хорошим тоном программирования для объектов, содержащих выделенную динамическую память, является или реализация пары оператор присваивания + конструктор копирования или их закрытие

Можно, пожалуйста по-подробнее про закрытие.

И у меня остался вопрос про вектор ссылок.
Можно ли это организовать, то есть определить vector<Cls_A&>, или нет ?
 
E

European

Можно ли это организовать, то есть определить vector<Cls_A&>, или нет ?
Нет
Можно, пожалуйста по-подробнее про закрытие.
Конструктор копирования и оператор присваивания объявляются как private и не реализуются
 
M

Monarh

Теперь всё встало на свои места :)
Спасибо большое !!!
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!