47

据我所知,我应该在析构函数中销毁我创建的所有内容,new并关闭打开的文件流和其他流。但是,我对 C++ 中的其他对象有一些疑问:

  • std::vectorstd::strings:它们会自动销毁吗?

  • 如果我有类似的东西

    std::vector<myClass*> 
    

    指向类的指针。调用向量析构函数时会发生什么?
    它会自动调用 的析构函数myClass吗?或者只有向量被破坏,但它包含的所有对象仍然存在于内存中?

  • 如果我在一个类中有一个指向另一个类的指针会发生什么,比如:

    class A {
      ClassB* B;
    }
    

    并且 A 类在代码中的某个点被销毁。B 类也会被销毁,还是指针和 B 类仍然存在于内存中的某个地方?

4

7 回答 7

52

std::vector 和 std::strings:它们会自动销毁吗?

是的(假设成员变量不是指向std::vectorand的指针std::string)。

如果我有类似 std::vector 的东西,当调用向量析构函数时会发生什么?它会自动调用 myClass 的析构函数吗?或者只有向量被破坏,但它包含的所有对象仍然存在于内存中?

如果vector<MyClass>那么包含在向量中的所有对象都将被销毁。如果vector<MyClass*>那么所有对象都必须显式地deleted (假设被破坏的类拥有 中的对象vector)。第三种选择是vector智能指针,例如,在这种情况下,不需要明确地dvector<shared_ptr<MyClass>>的元素。vectordelete

如果我在一个类中有一个指向另一个类的指针会发生什么

B必须明确deleted . 同样,可以使用智能指针来处理B.

于 2012-08-22T08:18:54.787 回答
6

您只需要担心您动态创建的内存(当您使用new. 保留内存时)

例如:

Class Myclass{
   private:
       char* ptr;
   public:
       ~Myclass() {delete[] ptr;};
}
于 2012-08-22T08:26:04.027 回答
3
  • 如果它们在自动存储中,是的。您可以拥有std::string* s = new std::string,在这种情况下,您必须自己删除它。

  • 没什么,您需要手动删除您拥有的内存(用于分配的内存new)。

  • 如果你分配bnew,你应该在析构函数中明确地销毁它。

一个好的经验法则是对代码中delete/delete[]的每一个new/new[]都使用 a。

更好的经验法则是使用 RAII,并使用智能指针而不是原始指针。

于 2012-08-22T08:19:25.990 回答
3

这取决于。std::vector并且它们std::string都有MyClass一个共同点——如果你将一个变量声明为这些类型中的任何一种,那么它将在堆栈上分配,对于你所在的当前块是本地的,并在该块结束时被破坏。

例如

{
    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
于 2012-08-22T08:25:50.857 回答
2

如果我有类似 std::vector 的东西,当调用向量析构函数时会发生什么?

这取决于。

如果你有一个values std::vector <MyClass>向量,那么向量的析构函数会为向量中的每个实例调用析构函数MyClass

如果您有一个指针 std::vector <MyClass*>向量,那么您有责任删除MyClass.

如果我在一个类中有一个指向另一个类的指针会发生什么

ClassB实例将保留在内存中。ClassA让析构函数为您完成工作的可能方法是创建B实例成员或智能指针。

于 2012-08-22T08:20:55.877 回答
1

std::vectorstd::string据我所知,所有其他 STL 容器都有自动析构函数。这就是为什么最好使用这些容器而不是使用这些容器的原因newdelete因为这样可以防止内存泄漏。

只有当您的向量是对象向量 ( ) 而不是指向对象的指针向量 () 时,myClass才会调用您的析构函数。myClassstd::vector< myClass >myClassstd::vector< myClass* >

在第一种情况下,析构函数也将为其每个元素std::vector调用析构函数;myClass在第二种情况下, 的析构函数std::vector将调用 的析构函数myClass*,这意味着它将释放用于存储每个指针的空间,但不会释放用于存储myClass对象本身的空间。

您指向的Class B对象不会被销毁,但分配用于存储其指针的空间将被释放。

于 2012-08-22T08:34:16.440 回答
1
  1. 是的。std::vector并且std::string在它们超出范围时自动调用,还调用包含的对象的析构函数(for std::vector)。

  2. 如前所述,std::vector当它超出范围时被销毁,调用所包含对象的析构函数。但实际上,在这种情况下,包含的对象是指针,而不是指针所指向的对象。所以你必须delete手动给他们。

  3. 同(2)。A 将被销毁,因此指针,但不是 B 指向的类。您必须为 A 提供deleteB的析构函数。

In C++11 there is a very useful solution: use std::unique_pointer. Can be use only to point a single object and this will be deleted when the pointer goes out of scope (for example when you destroy your std::vector).

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

于 2012-08-22T08:37:28.797 回答