开发者

Avoiding new() in initialization of static members?

开发者 https://www.devze.com 2023-03-18 00:47 出处:网络
The code in question is as follows: header: class Vec3d : public Object { public: static linearalgebra::Vec3d* X_AXIS;

The code in question is as follows:

header:


  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();
  };

implementation:

  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]; }

Is there a way of not using these new() operators, but without adding any new helper variables?

The types must be exactly as they are, to be compatible with the rest of the program.

EDIT: guessing from the answers, new() must be used if no helper variables are used. Is it true? Thus, I might add 开发者_StackOverflow中文版the helper variables. This is a compiler--generated code anyway, so no problem, as long as the headers are readable.

Would the following be ok? Now Valgrind says there are no leaks.


  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};


Is it ok in C++, if these pointers are never freed?

Define "OK". Will your program function? Yes. Is it a good idea? No!

It seems to me that you would be better off with this:

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]};


They are allocated, so you are leaking at exit. You can create a static method on Vec3d to dispose of the memory on shutdown (call it before your program exits).


If you want to keep everything like that, you can do that (which is not good design but should work). I didn't try to build, but should be ok.

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;
}


Any memory resource that is acquired but not given back is considered to be a memory leak. So if you obtained dynamic memory using new() unless you release the allocated memory by callnig delete() you are causing a memory leak.

What are the options you have?

You can have a static method, which calls delete on each of those resources to explicitly deallocate the allocated memory before exiting from your program.

A better alternative is:
You should consider using Smart Pointers instead of raw pointers.
With smart pointers You don't have to bother about calling delete explicitly once you are using smart pointers. Once there are no remaining references to those static types, they will be deleted implicitly. This way each resource itself takes care of its deallocation.


If you don't deallocate memory after new then it is a memory leak. You must delete/delete[].

If you want to disallow using new for Vec3d, then make them private and unimplemented:

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

This way compiler will not allow to use new() on Vec3d. Also you can think about creating this variable on automatic storage. Simply don't declare them as pointer, but as objects.

static linearalgebra::Vec3d X_AXIS;


It is a memory leak. Any variable allocated with new must be deleted with the delete keyword.

You could try to make another static variable that acts as a reference counter. In the constructor you add +1 to it, and in the destructor you do -1 on it. In the destructor after doing the minus one you check if the variable is 0 and if so.. you call delete on the static members.

Header:

static int  _refCount;

Implementation:

int Vec3d::_refCount = 0;

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

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

..or you could just use a Smart Pointer implementation.


  1. use smart pointers to handle automatic memory deallocation

  2. add a static function to deallocate memory and register it in "atexit"

0

精彩评论

暂无评论...
验证码 换一张
取 消