带向量,指针的C ++析构函数,

时间:2012-08-22 08:15:39

标签: c++ destructor

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

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

  • 如果我有类似

    的内容
    std::vector<myClass*> 
    

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

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

    class A {
      ClassB* B;
    }
    

    和A类在代码中的某个点被销毁。 B类是否会被销毁,或者只是指针和B类仍将存在于内存的某个地方?

8 个答案:

答案 0 :(得分:37)

  

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

是(假设成员变量不是std::vectorstd::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::vectorstd::stringMyClass都有一个共同点 - 如果你声明一个变量是这些类型中的任何一个,那么它将在堆栈上分配,在当前块的本地你进去了,当那个街区结束时被毁坏。

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::vectorstd::string据我所知,所有其他STL容器都有自动析构函数。这就是为什么通常更好地使用这些容器而不是newdelete,因为您将防止内存泄漏。

只有当您的向量是myClass个对象(myClass)的向量而不是指向std::vector< myClass >个对象的向量({{}时,才会调用myClass析构函数。 1}})。

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

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

答案 6 :(得分:1)

  1. 是。 std::vectorstd::string在超出范围时自动调用,同时调用所包含对象的析构函数(对于std::vector)。

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

  3. 与(2)相同。 A将被销毁,所以指针,但不是B类指向。您必须为delete B。

  4. 提供A的析构函数

    在C ++ 11中有一个非常有用的解决方案:使用std::unique_pointer。只能用于指向单个对象,当指针超出范围时(例如,当您销毁std::vector时),这将被删除。

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

答案 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

那是你想要的吗?