据我所知,我应该在析构函数中销毁我使用new
创建的所有内容并关闭打开的文件流和其他流。
但是,我对C ++中的其他对象有些怀疑:
std::vector
和std::string
s:它们会自动销毁吗?
如果我有类似
的内容std::vector<myClass*>
指向类的指针。调用向量析构函数时会发生什么?
它会自动调用myClass
的析构函数吗?或者只有矢量被销毁,但它包含的所有对象在内存中仍然存在?
如果我有一个指向类中另一个类的指针会发生什么,比如说:
class A {
ClassB* B;
}
和A类在代码中的某个点被销毁。 B类是否会被销毁,或者只是指针和B类仍将存在于内存的某个地方?
答案 0 :(得分:37)
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
的破坏。
答案 1 :(得分:5)
您只需要担心动态创建的内存(当您使用new
保留内存时。)
例如:
Class Myclass{
private:
char* ptr;
public:
~Myclass() {delete[] ptr;};
}
答案 2 :(得分:2)
如果他们在自动存储中,是的。你可以拥有std::string* s = new std::string
,在这种情况下你必须自己删除它。
什么都没有,你需要手动删除你拥有的内存(对于用new
分配的内存)。
如果您使用b
分配new
,则应明确地在析构函数中销毁它。
一个好的经验法则是为代码中的每个delete/delete[]
使用new/new[]
。
更好的经验法则是使用RAII,并使用智能指针而不是原始指针。
答案 3 :(得分:2)
这取决于。 std::vector
和std::string
和MyClass
都有一个共同点 - 如果你声明一个变量是这些类型中的任何一个,那么它将在堆栈上分配,在当前块的本地你进去了,当那个街区结束时被毁坏。
E.g。
{
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
它(无论它是否在向量中),否则指向的内存没有任何反应。如果你有一个包含指向其他对象的指针的类,那么可能必须在析构函数中删除它们(取决于该类是否拥有这些对象)。请注意,在C ++ 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's internal string ptr and then be destroyed
答案 4 :(得分:1)
如果我有类似std :: vector的东西,那么在调用向量析构函数时会发生什么?
取决于。
如果你有一个值 std::vector <MyClass>
的向量,那么向量的析构函数会为向量中的MyClass
的每个实例调用析构函数。
如果您有指针 std::vector <MyClass*>
的向量,那么您有责任删除MyClass
的实例。
如果我有一个指向类
中另一个类的指针会发生什么
ClassB
实例将保留在内存中。使ClassA
析构函数为您完成工作的可能方法是使B
成为实例成员或智能指针。
答案 5 :(得分:1)
std::vector
,std::string
据我所知,所有其他STL容器都有自动析构函数。这就是为什么通常更好地使用这些容器而不是new
和delete
,因为您将防止内存泄漏。
只有当您的向量是myClass
个对象(myClass
)的向量而不是指向std::vector< myClass >
个对象的向量({{}时,才会调用myClass
析构函数。 1}})。
在第一种情况下,std::vector< myClass* >
的析构函数也会为每个元素调用std::vector
的析构函数;在第二种情况下,myClass
的析构函数将调用std::vector
的析构函数,这意味着它将释放存储每个指针所用的空间,但不会释放用于存储myClass*
的空间对象本身。
您指向的myClass
个对象不会被销毁,但分配用于存储其指针的空间将被释放。
答案 6 :(得分:1)
是。 std::vector
和std::string
在超出范围时自动调用,同时调用所包含对象的析构函数(对于std::vector
)。
如前所述,std::vector
在超出范围时被销毁,调用所包含对象的析构函数。但事实上,在这种情况下,包含的对象是指针,而不是指针指向的对象。因此,您必须手动delete
。
与(2)相同。 A将被销毁,所以指针,但不是B类指向。您必须为delete
B。
在C ++ 11中有一个非常有用的解决方案:使用std::unique_pointer
。只能用于指向单个对象,当指针超出范围时(例如,当您销毁std::vector
时),这将被删除。
答案 7 :(得分:-2)
据我了解,这应该如下:
vector <int> test_vector = {1,2,3,4,5,6,7} // Call vector constructor
... Any manipulations with a vector ...
test_vector.~vector(); // Call vector destructor
那是你想要的吗?