类内非静态字段初始化 + 对象池 - >降低可维护性/可读性

in-class in-line non-static field initialization + object pool -> decrease maintainability/readability

本文关键字:gt 可读性 可维护性 静态 字段 初始化 对象      更新时间:2023-10-16

创建&破坏物体,合并是可能的。

在某些情况下,我不想使用自定义分配器或char[]等低级技术。
另一种方法是创建对象池
但是,该技术与课堂字段(内联(初始化相关。

起初,我根本不认为这是一个问题。
但是,该模式保持了一百次的重新表现,我认为我应该有一些相对。

示例

假设我的程序的第一个版本看起来像这样: -

class Particle{
    int lifeTime=100;  //<-- inline initialization
    //.... some function that modify "lifeTIme"
};
int main(){
    auto p1=new Particle();
    delete p1;
    //... many particle created & deleted randomly ...
};

采用对象池后,我的程序可能是: -

class Particle{
    int lifeTime=100;   //<---- maintainability issue
    void reset(){
        lifeTime=100;   //<---- maintainability issue
    }
};
int main(){
    auto* p1=pool.create(); 
    //.... "Particle::reset()" have to be called somewhere.
};

重复代码引起了一些可维护性问题。

问题

如何在不牺牲代码维护性和可读性的情况下对具有内联定位化的现有对象采用对象池?

我目前的解决方法

我通常让构造函数调用reset()

class Particle{
    int lifeTime;  
    public: Particle(){ 
        reset();    //<---- call it here, or "pool" call it
    }
    void reset(){
        lifeTime=100;  
    }
};

缺点:它可降低与旧的内线定义相比的代码可读性: -

int lifeTime=100;    

对不起,如果它太初学者问题,我是C 的新手。

这是std::unique_ptr<>的通常用户酶:

class Base {
    static constexpr int lifespan = 100;
    int lifetime = lifespan;
public:
    void reset() noexcept { lifetime = lifespan; }
}
struct Deleter {
    void operator ()(Base* const b) const {
        b->reset();
    }
};
struct Particle : Base {
    // ...
};
struct Pool {
    std::unique_ptr<Particle, Deleter> create() {
        // ...
    }
}
int main() {
    // ...
    auto p1 = pool.create();
}

解决方案的解决方案实际上取决于

的组合
  • 为什么需要池对象?
  • 为什么对象需要具有100的默认lifeTime
  • 为什么对象需要更改其lifeTime
  • 为什么从池中获得的现有对象需要将其lifeTime重置为100

您已经部分回答了第一个,尽管我敢打赌,除了"您认为您需要提高绩效"之外,我敢打赌,提高性能的既定目标并不是基于其他任何内容。确实,这样的目标应该基于测量的性能不足,否则它不过是过早优化。

无论如何,如果我为了讨论,上面的所有问题都有良好的答案,我会做以下;

class Particle
{   
   public:
      // member functions that provide functions used by `main()`.
   private:     // note all the members below are private
       Particle();
       void reset()
       {
            lifeTime=100;
       };
       friend class Pool;
   };
   class Pool
   {
        public:
             Particle *create()
             {
                   Particle *p;
                    // obtain an object for p to point at
                    //    that may mean release it from some "pool" or creating a new one
                    p->reset();
                    return p;
             };
             void give_back(Particle *&p)
             {
                  // move the value of p back into whatever the "pool" is
                  p = NULL;    //  so the caller has some indication it should not use the object
             };
   };
int main()
{
     // presumably pool is created somehow and visible here     
     auto* p1=pool.create(); 
     // do things with p1
     pool.give_back(p1);    // we're done with p1
     auto *p2 = pool.create();
      // p2 might or might not point at what was previously p1
}

请注意,值100仅出现在reset()函数中。

使构造函数私有的原因和Pool A friend是为了防止意外创建新对象(即强制使用池(。

可选,使Particle::reset()public允许main()调用p1->reset(),但这不是必需的。但是,从池中获得的所有对象(无论创建新鲜还是重复使用(都将被重置。

我可能还会使用std::unique_ptr<Particle>,因此,如果您忘记将对象还给池中,则可以正确管理对象的寿命。我将把这种事情作为练习留下。