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



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

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

  • 如果我有类似的东西

    std::vector<myClass*> 
    

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

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

    class A {
      ClassB* B;
    }
    

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

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的销毁。

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

例如:

Class Myclass{
   private:
       char* ptr;
   public:
       ~Myclass() {delete[] ptr;};
}
  • 如果它们在自动存储中,是的。你可以有 std::string* s = new std::string ,在这种情况下,您必须自己删除它。

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

  • 如果使用 new 分配了b,则应在析构函数中显式销毁它。

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

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

这取决于。 std::vectorstd::stringMyClass都有一个共同点 - 如果你将一个变量声明为这些类型中的任何一个,那么它将被分配到堆栈上,是你所在的当前块的本地,并在该块结束时被销毁。

例如

{
    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

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

这要看情况。

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

如果您有指针向量std::vector <MyClass*>那么您负责删除 MyClass 的实例。

如果我有一个指向类内另一个类的指针会发生什么情况

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

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

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

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

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

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

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

  3. 同(2(。A 将被销毁,指针也是如此,但 B 类不会指向。您必须为 A 提供一个delete B 的析构函数。

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

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

最新更新