C++ деструкторы с векторами, указатели, - программирование
Подтвердить что ты не робот

C++ деструкторы с векторами, указатели,

Насколько я знаю, я должен уничтожить в деструкторах все, что я создал с помощью new, и закрыть открытые потоки и другие потоки. Однако у меня есть некоторые сомнения относительно других объектов в С++:

  • std::vector и std::string s: они автоматически уничтожаются?

  • Если у меня есть что-то вроде

    std::vector<myClass*> 
    

    указателей на классы. Что происходит, когда вызывается векторный деструктор?
    Будет ли он автоматически вызывать деструктор myClass? Или только вектор уничтожен, но все содержащиеся в нем объекты все еще существуют в памяти?

  • Что произойдет, если у меня есть указатель на другой класс внутри класса, скажем:

    class A {
      ClassB* B;
    }
    

    и класс A в какой-то момент кода уничтожается. Будет ли уничтожен класс B или только указатель, а класс B будет все еще существовать где-то в памяти?

4b9b3361

Ответ 1

std::vector и std:: strings: автоматически ли они уничтожаются?

Да (предполагается, что переменные-члены не являются указателями на std::vector и std::string).

Если у меня есть что-то вроде std::vector, что происходит, когда вызывается векторный деструктор? Будет ли он автоматически вызывать деструктор myClass? Или только вектор уничтожен, но все содержащиеся в нем объекты все еще существуют в памяти?

Если vector<MyClass>, то все объекты, содержащиеся в векторе, будут уничтожены. Если vector<MyClass*>, тогда все объекты должны быть явно delete d (при условии, что разрушенный класс владеет объектами в vector). Третьей альтернативой является vector интеллектуальных указателей, таких как vector<shared_ptr<MyClass>>, и в этом случае элементы vector не должны быть явно delete d.

Что произойдет, если у меня есть указатель на другой класс внутри класса

B должен быть явно delete d. Опять же, интеллектуальный указатель можно использовать для обработки разрушения B.

Ответ 2

Вам нужно только беспокоиться о динамической памяти, которую вы создали (когда вы резервируете память с помощью new.)

Например:

Class Myclass{
   private:
       char* ptr;
   public:
       ~Myclass() {delete[] ptr;};
}

Ответ 3

  • если они находятся в автоматическом хранилище, да. У вас может быть std::string* s = new std::string, и в этом случае вы должны удалить его самостоятельно.

  • ничего, вам нужно вручную удалить принадлежащую вам память (для выделенной памяти new).

  • если вы выделили b с помощью new, вы должны явно уничтожить его в деструкторе.

Хорошим правилом является использование delete/delete[] для каждого new/new[], которое у вас есть в коде.

Лучшим правилом является использование RAII и использование интеллектуальных указателей вместо необработанных указателей.

Ответ 4

Это зависит. std::vector и std::string и MyClass все имеют 1 общую черту - если вы объявляете переменную какой-либо из этих типов, то она будет выделена в стеке, будет локальной для текущего блока, в котором вы находитесь, и разрушаться, когда этот блок заканчивается.

например.

{
    std::vector<std::string> a;
    std::string b;
    MyClass c;
} //at this point, first c will be destroyed, then b, then all strings in a, then a.

Если вы дойдете до указателей, вы догадались правильно: только память, которую занимает сам указатель (обычно 4 байтового целого), автоматически освобождается при выходе из области. Ничего не происходит с указанной памятью, если вы явно не указали ее delete (будь то в векторе или нет). Если у вас есть класс, содержащий указатели на другие объекты, вам может потребоваться удалить их в деструкторе (в зависимости от того, принадлежит ли этот класс этим объектам). Обратите внимание, что в С++ 11 есть классы указателей (называемые интеллектуальными указателями), которые позволяют обрабатывать указатели аналогично "нормальным" объектам:

Пример:

{
    std::unique_ptr<std::string> a = make_unique<std::string>("Hello World");
    function_that_wants_string_ptr(a.get());
} //here a will call delete on it internal string ptr and then be destroyed

Ответ 5

Если у меня есть что-то вроде std::vector, что происходит, когда вызывается векторный деструктор?

Это зависит.

Если у вас есть вектор значений std::vector <MyClass>, деструктор вектора вызывает деструктор для каждого экземпляра MyClass в векторе.

Если у вас есть вектор указателей std::vector <MyClass*>, вы несете ответственность за удаление экземпляров MyClass.

Что произойдет, если у меня есть указатель на другой класс внутри класса

ClassB экземпляр останется в памяти. Возможные способы создания ClassA деструктора для выполнения задания для вас - сделать B членом экземпляра или интеллектуальным указателем.

Ответ 6

std::vector, std::string, и насколько я знаю, все остальные контейнеры STL имеют автоматические деструкторы. Вот почему часто лучше использовать эти контейнеры вместо new и delete, так как вы предотвратите утечку памяти.

Деструктор myClass будет вызываться только в том случае, если ваш вектор является вектором объектов myClass (std::vector< myClass >) вместо вектора указателей на объекты myClass (std::vector< myClass* >).

В первом случае деструктор std::vector также вызовет деструктор myClass для каждого из его элементов; во втором случае деструктор std::vector вызовет деструктор myClass*, что означает, что он освободит пространство, которое будет сохранено для каждого указателя, но не освободит место, которое будет сохранено для самих объектов myClass.

Объекты Class B, на которые вы указываете, не будут уничтожены, но пространство, назначенное для хранения его указателя, будет освобождено.

Ответ 7

  • Да. std::vector и std::string автоматически, когда они заканчиваются вне области видимости, вызывая также деструктор содержащихся объектов (для std::vector).

  • Как уже говорилось, std::vector уничтожается, когда он заканчивается из области видимости, вызывая деструктор содержащихся объектов. Но на самом деле в этом случае содержащиеся объекты являются указателями, а не объектом, указанным указателями. Поэтому вы должны delete их вручную.

  • То же, что и (2). A будет уничтожен, и указатель, но не класс B, указал. Вы должны предоставить деструктор для A, который delete B.

В С++ 11 есть очень полезное решение: используйте std::unique_pointer. Может использоваться только для указания одного объекта, и это будет удалено, если указатель выходит из области видимости (например, когда вы уничтожаете std::vector).

http://en.cppreference.com/w/cpp/memory/unique_ptr

Ответ 8

Насколько я понимаю, это должно работать следующим образом:

vector <int> test_vector = {1,2,3,4,5,6,7} // Call vector constructor

... Любые манипуляции с вектором... test_vector. ~ Vector(); // Вызываем деструктор вектора

Это то, что вы хотели?