C ++静态类成员,谁清理乱七八糟的东西?

时间:2011-12-20 15:56:26

标签: c++ memory

我想知道我的代码的哪一部分将在不再需要时释放动态分配但静态的类成员。请参阅以下代码:classPrinter在所有A - 对象之间共享,并在创建类A的第一个实例时创建。只是为了确定:classPrinter - 对象在退出程序时会自动被破坏,对吗?

A.H

class A {
static B* classPrinter;
}

a.cpp

#include "a.h"
B A::classPrinter = new B();

A::A() { ...}

6 个答案:

答案 0 :(得分:20)

  

只是为了确定:somePrinter - 对象在退出程序时会自动被破坏,对吗?

由于这是C ++,答案是“不”。对于使用new分配的所有内容,必须调用相应的delete。如果没有发生,则对象泄漏。但为什么要动态分配呢?此

class A {
  static B classPrinter;
}

B A::classPrinter;

的行为与您的代码相似,只是在程序结束时将classPrinter销毁。

但是,你写的是

  

classPrinter在所有A对象之间共享,并在创建类A的第一个实例时创建。

您问题中的代码不会这样做。 如果您想要这样做,请执行以下操作:

class A {
  static std::shared_ptr<B> classPrinter;
}

std::shared_ptr<B> A::classPrinter;

A::A()
{
  if(!classPrinter)
    classPrinter.reset(new B());
}

智能指针将确保删除对象。

答案 1 :(得分:10)

不,永远不会自动删除使用new创建的对象。您应始终提供匹配的delete以防止内存泄漏。

在这种情况下,最简单的解决方案是拥有一个静态对象,而不是一个指向动态对象的静态指针 - 没有任何理由可以提供额外的间接级别。

// header file
class A {
    static B classPrinter;
};

// source file
B A::classPrinter;

或者如果你想延迟构造直到需要对象(如果其他翻译单元中的静态对象需要从构造函数访问它,则避免潜在的问题):

class A {
    static B & classPrinter() {
        static B instance;
        return instance;
    }
};

在其他情况下,当您确实需要动态分配时,应始终使用智能指针或其他RAII对象管理动态对象。

答案 2 :(得分:3)

A::classPrinter指向的对象的析构函数将不会被调用。

如果你认为它只不过是逻辑;哪个是匹配的delete - 在正常情况下会调用对象的dtor?

占用的内存将再次被标记为空闲并返回系统,至少在所有现代系统中都是如此。

答案 3 :(得分:0)

如果A::classPrinter在多个成员之间共享,可能使用std :: shared_ptr而不是原始指针?在对它的所有引用都消失后,它将自动删除。

但是,是的,在程序退出后,内存将被收回,至少在我能想到的所有操作系统上......

答案 4 :(得分:0)

您需要创建一些包装器或使用类似shared_ptr的东西来保证dtor调用。

答案 5 :(得分:0)

静态(就静态成员变量而言)本身就意味着,始终存在。

如果你制作一个静态指针,你根本无法在一个有意义的点解除分配。你需要更多的背景。

如果您希望只有在拥有静态成员所有者类的实例时才存在共享数据,那么您需要一个静态计数器。每次创建实例时都会分配一个新的静态值,并且计数器== 0.每当删除所有者类的最后一个实例时,都会释放当前的静态值。

否则,您将不得不深入研究共享或智能指针以解除分配,但即便如此,您也会遇到问题。如果智能指针看不到更多引用和释放,它可能会过早地这样做。如果它处于解除分配状态,那么当您再次需要该信息时,这意味着什么。你分配了一个新的静态值吗?

如果静态成员需要始终存在,无论您是否拥有所有者类的实例,您应该考虑将指针更改为引用或实例。