【问题标题】:Avoiding new() in initialization of static members?在静态成员的初始化中避免 new()?
【发布时间】:2011-07-08 09:19:20
【问题描述】:

有问题的代码如下:

标题:


  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 = 轴[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};

【问题讨论】:

    标签: c++ static-initializer


    【解决方案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]};
    

    【讨论】:

    • 谢谢!我在问题中添加了一个类似的代码来询问它是否有效,因为我还没有看到你的答案,只是想看看,在我将它添加到问题之前,你在答案中添加了类似的代码。谢谢,这种方式你确认这是一个好方法。
    【解决方案2】:

    它们已分配,因此您在退出时泄漏。您可以在 Vec3d 上创建一个静态方法以在关闭时释放内存(在程序退出之前调用它)。

    【讨论】:

      【解决方案3】:

      如果您想保留这样的所有内容,您可以这样做(这不是好的设计,但应该可以)。我没有尝试构建,但应该没问题。

      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】:

        任何被获取但未归还的内存资源都被认为是内存泄漏。因此,如果您使用new() 获得动态内存,除非您通过调用delete() 释放分配的内存,否则您将导致内存泄漏。

        你有什么选择?

        您可以有一个静态方法,它在每个资源上调用 delete 以在退出程序之前显式解除分配的内存。

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

        【讨论】:

          【解决方案5】:

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

          如果您想禁止将new 用于Vec3d,则将它们设为private 并且未实现:

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

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

          static linearalgebra::Vec3d X_AXIS;
          

          【讨论】:

            【解决方案6】:

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

            您可以尝试创建另一个静态变量作为引用计数器。在构造函数中添加+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 实现。

            【讨论】:

              【解决方案7】:
              1. 使用智能指针来处理自动内存释放

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-07-18
                • 2014-06-24
                • 1970-01-01
                • 1970-01-01
                • 2015-05-18
                • 1970-01-01
                相关资源
                最近更新 更多