C++ деструкторы с векторами, указатели,
Насколько я знаю, я должен уничтожить в деструкторах все, что я создал с помощью new
, и закрыть открытые потоки и другие потоки.
Однако у меня есть некоторые сомнения относительно других объектов в С++:
-
std::vector
и std::string
s: они автоматически уничтожаются?
-
Если у меня есть что-то вроде
std::vector<myClass*>
указателей на классы. Что происходит, когда вызывается векторный деструктор?
Будет ли он автоматически вызывать деструктор myClass
? Или только вектор уничтожен, но все содержащиеся в нем объекты все еще существуют в памяти?
-
Что произойдет, если у меня есть указатель на другой класс внутри класса, скажем:
class A {
ClassB* B;
}
и класс A в какой-то момент кода уничтожается. Будет ли уничтожен класс B или только указатель, а класс B будет все еще существовать где-то в памяти?
Ответы
Ответ 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(); // Вызываем деструктор вектора
Это то, что вы хотели?