在静态成员的初始化中避免使用new()?

时间:2011-07-08 09:19:21

标签: c++ static-initializer

有问题的代码如下:

头:


  class Vec3d : public Object {
    public:
      static linearalgebra::Vec3d* X_AXIS;
      static linearalgebra::Vec3d* Y_AXIS;
      static linearalgebra::Vec3d* Z_AXIS;
      static linearalgebra::Vec3d* AXES[3];

      static int f();
  };

实现:

  Vec3d* Vec3d::X_AXIS = new Vec3d();
  Vec3d* Vec3d::Y_AXIS = new Vec3d();
  Vec3d* Vec3d::Z_AXIS = new Vec3d();
  Vec3d* Vec3d::AXES[3] = {Vec3d::X_AXIS, new Vec3d(),Vec3d::Z_AXIS};

int Vec3d::f() { X_AXIS = AXES[2]; }

有没有办法不使用这些new()运算符,但是没有添加任何新的辅助变量?

类型必须与它们完全一致,才能与程序的其余部分兼容。

编辑:从答案中猜测,如果没有使用辅助变量,则必须使用new()。这是真的吗?因此,我可能会添加辅助变量。这是一个编译器生成的代码,所以没有问题,只要标题是可读的。

以下是否可以?现在Valgrind说没有泄漏。


  static Vec3d INIT_X_AXIS;
  static Vec3d INIT_Y_AXIS;
  static Vec3d INIT_Z_AXIS;
  static Vec3d INIT_AXES_1;

  Vec3d* Vec3d::X_AXIS = &INIT_X_AXIS;
  Vec3d* Vec3d::Y_AXIS = &INIT_Y_AXIS;
  Vec3d* Vec3d::Z_AXIS = &INIT_Z_AXIS;
  Vec3d* Vec3d::AXES[3] = {Vec3d::X_AXIS, &INIT_AXES_1, Vec3d::Z_AXIS};

7 个答案:

答案 0 :(得分:1)

他们被分配,所以你在退出时泄漏。你可以在Vec3d上创建一个静态方法来在关机时处理内存(在程序退出之前调用它)。

答案 1 :(得分:1)

获取但未返回的任何内存资源都被视为内存泄漏。因此,如果您使用new()获取动态内存,除非您通过callnig delete()释放已分配的内存,否则会导致内存泄漏。

您有哪些选择?

您可以使用静态方法,在每个资源上调用delete,以便显式在退出程序之前释放已分配的内存。

更好的选择是:
您应该考虑使用智能指针而不是原始指针 使用智能指针一旦使用智能指针,您就不必为显式调用delete而烦恼。一旦没有对这些静态类型的剩余引用,它们将被隐式删除。这样每个资源本身都会处理它的释放。

答案 2 :(得分:1)

  

如果这些指针永远不会被释放,那么在C ++中是否正常?

定义“确定”。你的程序会起作用吗?是。这是个好主意吗? 否!

在我看来,你最好还是这样:

class Vec3d : public Object {
public:
    static linearalgebra::Vec3d xAxisMemory;
    static linearalgebra::Vec3d yAxisMemory;
    static linearalgebra::Vec3d zAxisMemory;
    static linearalgebra::Vec3d axesMemory[3];

    static linearalgebra::Vec3d* X_AXIS;
    static linearalgebra::Vec3d* Y_AXIS;
    static linearalgebra::Vec3d* Z_AXIS;
    static linearalgebra::Vec3d* AXES[3];

    static int f();
};


Vec3d Vec3d::xAxisMemory;
Vec3d Vec3d::xAxisMemory;
Vec3d Vec3d::xAxisMemory;
Vec3d Vec3d::axesMemory[3];

Vec3d* Vec3d::X_AXIS = &xAxisMemory;
Vec3d* Vec3d::Y_AXIS = &yAxisMemory;
Vec3d* Vec3d::Z_AXIS = &zAxisMemory;
Vec3d* Vec3d::AXES[3] = {&axesMemory[0], &axesMemory[1], &axesMemory[2]};

答案 3 :(得分:1)

如果你想保留这样的一切,你可以做到(这不是好的设计,但应该工作)。我没有尝试构建,但应该没问题。

Vec3d* Vec3d::X_AXIS = NULL;
Vec3d* Vec3d::Y_AXIS = NULL;
Vec3d* Vec3d::Z_AXIS = NULL;
Vec3d* Vec3d::AXES[3] = { 0 };

namespace {
    const struct Initializer {
        Initializer() {
            static Vec3d x, y, z;
            AXES[0] = X_AXIS = &x;
            AXES[1] = Y_AXIS = &y;
            AXES[2] = Z_AXIS = &z;
        }
    } Init;
}

答案 4 :(得分:0)

如果在new之后没有释放内存,那么就是内存泄漏。您必须delete/delete[]

如果您不允许new使用Vec3d,请将其设为private并且未实现:

class Vec3d {
private:
  void* operator new (std::size_t); // don't implement it
public:
//...
};

这样编译器就不允许在new()上使用Vec3d。您也可以考虑在自动存储上创建此变量。只是不要将它们声明为指针,而是将其声明为对象。

static linearalgebra::Vec3d X_AXIS;

答案 5 :(得分:0)

1)使用智能指针处理自动内存释放

2)添加一个静态函数来释放内存并在“atexit”中注册它

答案 6 :(得分:0)

这是内存泄漏。必须使用delete关键字删除使用new分配的任何变量。

您可以尝试创建另一个充当引用计数器的静态变量。在构造函数中,为它添加+1,并在析构函数中对其执行-1。在执行减1后的析构函数中,检查变量是否为0,如果是,则在静态成员上调用delete。

部首:

static int  _refCount;

实现:

int Vec3d::_refCount = 0;

Vec3d::Vec3d()
{
    _refCount += 1;
}

virtual Vec3d::~Vec3d()
{
    _refCount -= 1;
    if (_refCount == 0)
    {
        //delete all allocated memory in static variables
    }
}

..或者您可以使用Smart Pointer实施。