Как освободить содержимое вектора от его уничтожения?

Насколько я знаю, для обеих векторных объявлений:

//TYPE 1
std::vector<cls> vec;     //cls is user defined datatype(A class)

Память для вектора выделяется в стеке, а память содержимого в векторе выделяется в куче.

Это верно и для нижеследующей декларации (исправьте меня, если я ошибаюсь):

//TYPE 2
std::vector<cls*> vec;    //cls is user defined datatype(A class)

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

Но что происходит в типе 2, если я вставляю элементы, как показано ниже (при условии, что у меня есть надлежащий перегруженный конструктор), а затем вектор выходит за пределы области видимости:

vec.push_back(new cls(5));

Я явно попробовал очистить вызов, но деструктор не был вызван. Будет ли автоматически освобождаться память и вызываться деструкторы. Если нет, то как это достичь.

Также, где выделена память для вектора, а также содержимое, если я объявляю вектор как:

std::vector<cls*> *vec = new std::vector<cls*>;

Ответ 1

Вот почему у нас есть умные указатели.

{
    std::vector<std::unique_ptr<cls>> vec;

    // C++14 will allow std::make_unique
    vec.emplace_back(std::unique_ptr<cls>(new cls(5)));
}

Когда вектор выходит из области видимости, деструкторы unique_ptr будут вызываться и память будет освобождена.

В вашем случае с необработанными указателями вы должны delete создать delete все, что вы создали с помощью new вручную:

// Something along the lines of this.
for (auto&& elem : vec) {
    delete elem;
}

Также, где выделена память для вектора, а также содержимое, если я объявляю вектор как:

Вы выделяете вектор с помощью new, поэтому он будет в куче.

Ответ 2

Но что происходит в типе 2, если я вставляю элементы, как показано ниже (при условии, что У меня есть надлежащий перегруженный конструктор), а затем вектор выходит области:

Произойдет утечка памяти - вам нужно будет последовательно итератировать ваш вектор и delete каждый элемент.

Ответ 3

Если вы храните указатель на объект в векторе, вам нужно будет удалить элементы перед уничтожением вектора (или иметь утечку памяти, но это не очень хорошо). Но вы не должны использовать "сырые" указатели. Если вы используете, например, unique_ptr<cls> вместо *cls, проблема решена.

Итак, вместо:

vec.push_back(new cls(5))

использование

vec.push_back(unique_ptr(new cls(5)))

или

vec.push_back(make_unique<cls>(5))

и вам не придется беспокоиться о том, чтобы найти место для итерации по вектору и удалить контент.

Очень мало ситуаций, когда new vector<...> является "правильным". Если вы это сделаете, подумайте, действительно ли это необходимо.

Ответ 4

Нет для этого типа, вы можете отбросить новый cls byt, выполняющий vec.push_back (new cls)

//TYPE 2
vector<cls*> vec;    //cls is user defined datatype(A class)

однако вектор очистит память переменных указателя, но не к экземплярам, ​​на которые они указывают, вам нужно запустить delete на каждом cls * внутри vec. В противном случае у вас есть утечка памяти.

Ответ 5

A std::vector не будет delete сохраненных в нем объектов, если они динамически распределены. Вам придется сделать это самостоятельно. Лучше всего избегать использования необработанной памяти - обычно вы хотите обернуть ваши указатели в std::shared_ptr или std::unique_ptr. Они оба автоматически освободят память для вас.

Не создавайте vector с помощью new.

Ответ 6

Память для вектора не обязательно выделяется в стеке. Как показано в последнем фрагменте, память для вектора может быть выделена из кучи.

Когда вектор выходит из области видимости из стека или когда вектор уничтожается с удалением, если он был выделен новым в куче, он автоматически уничтожит все его элементы. Однако обычные указатели не имеют деструктора и не делают ничего особенного с объектом, на который они указывают, когда они умирают. Таким образом, хотя очистка вектора указателей, уничтожает указатели, объекты, на которые они указывают, НЕ уничтожены.

Существует два решения. Прежде чем очистить вектор, проведите по каждому указателю в векторе и вызовите delete на нем. Лучший solutin - использовать умный указатель, такой уникальный_ptr. Когда unique_ptr уничтожается, объект, на который он указывает, автоматически удаляется.

Итак, с

vector<unique_ptr<cls>>

вы можете отбросить новые cls, как вы это сделали, и когда вектор уничтожен, все объекты cls, которые вы вставляете в вектор через unique_ptr, также уничтожены.

Ответ 7

Указатели вектора удерживания не отвечают за память, на которую указывают указатели. Когда вектор выходит из области видимости, он освобождает память, имеющуюся для указателей, а не память, на которую указывают эти указатели.

Это ваша ответственность за управление этой памятью. Вот почему вы должны использовать интеллектуальные указатели как std::unique_ptr или std::shared_ptr, чтобы избежать утечек памяти (это может произойти, если вы забыли удалить вручную).

Также, где выделена память для вектора, а также содержимое, если я объявляю вектор как:

vector<cls*> *vec = new vector<cls*>;

Вектор находится в куче, содержимое находится там, где оно было (например, оно может быть в куче, если вы выделили его new или в стеке, если вы сделали: cls myCls; cls* myPointerToCls = &cls;, а затем vec.push_back(myPointerToCls);)

Ответ 8

Хорошо много приятных ответов,

Вам нужно будет перебирать вектор и удалять каждый элемент отдельно

Я покажу небольшой пример:

class cls
{

public:
  cls(int x) :_a(x) {}
  ~cls() {cout<<"I'm Destroyed"<<endl ;}
 private:
 int _a;

};

int main()
{
vector<cls*> vec ;

for(auto i=1;i<=10;i++)
    vec.push_back(new cls(i));

for (auto it = vec.begin(); it != vec.end(); ++it) 
    delete *it;

{
vector<cls*> vec2 ;

vec2.push_back(new cls(10));
}
   //Here  vec2 out of scope
}

Вывод: Я разрушен < Только 10 раз >