首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类内非静态字段初始化+对象池->降低了可维护性/可读性。

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

Stack Overflow用户
提问于 2017-04-22 03:10:24
回答 2查看 57关注 0票数 0

为了提高创建和销毁对象时的性能,池是一种可能。

在某些情况下,我不想进入低级别的技术,如自定义分配程序或char[]

另一种方法是创建对象池

然而,这种技术并不适用于类内字段(内联)初始化。

一开始,我根本不认为这是个问题。

然而,这种模式不断地重复出现上百次,我认为我应该有一些对策。

示例

假设我的程序的第一个版本如下所示:

代码语言:javascript
复制
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 ...
};

在采用对象池之后,我的程序可以是:-

代码语言:javascript
复制
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()

代码语言:javascript
复制
class Particle{
    int lifeTime;  
    public: Particle(){ 
        reset();    //<---- call it here, or "pool" call it
    }
    void reset(){
        lifeTime=100;  
    }
};

的缺点:与旧的内联初始化相比,降低了代码的可读性:-

代码语言:javascript
复制
int lifeTime=100;    

对不起,如果这个问题太初学了,我是C++新手。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-04-22 03:43:19

这是std::unique_ptr<>常用的一种用法

代码语言:javascript
复制
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();
}
票数 1
EN

Stack Overflow用户

发布于 2017-04-22 03:55:17

这一问题的解决方案实际上取决于

  • 为什么你需要集合对象?
  • 为什么对象需要默认的lifeTime of 100
  • 为什么对象需要更改它们的lifeTime
  • 为什么从池中获取的现有对象需要将其lifeTime重置为100

你已经部分地回答了第一个问题,尽管我敢打赌你所说的提高性能的目标不是基于“你认为你需要提高性能”。实际上,这样一个目标应该建立在衡量业绩不够充分的基础上,否则,这只不过是过早的优化。

无论如何,如果我为了讨论而假设上述所有问题都有很好的答案,我会做以下几件事;

代码语言:javascript
复制
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()函数中。

将构造函数设置为私有函数和Poolfriend的原因是为了防止意外创建新对象(即强制使用池)。

或者,让Particle::reset()成为public允许main()调用p1->reset(),但这不是必需的。但是,从池中获得的所有对象(无论是新建对象还是重用对象)都将被重置。

我可能还会使用std::unique_ptr<Particle>,以便正确管理对象的生存期,例如,如果您忘记将对象返回到池中。我将把实现这类事情作为一项练习。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43554804

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档