続きのstory。テンプレートクラスによる自動メモリプール機能
フラグメンテーションによる動的割り当てが許可されていない安全ソフトウェアを検討してください。動的割り当ては、クラスexplicityがフラグメンテーションを避けるために演算子new
とdelete
を定義している場合にのみ許可されます。
ここで、私たちは得たいクラスのオペレータnew
とdelete
の明示的な定義を最適化する機会があります。一見すると、どのクラスから継承することもできるテンプレートクラスは、エンドユーザにとって最も簡単で分かりやすい方法です。
template<class T, unsigned size>
class MemoryPool
{
private:
struct Pool
{
bool allocated __attribute__ ((aligned (sizeof(void*))));
uint8_t memory[sizeof(T)] __attribute__ ((aligned (sizeof(void*))));
};
static std::array<uint8_t[sizeof(Pool)], size> memoryPool;
public:
void* operator new(std::size_t) noexcept
{
T* ret = nullptr;
for(auto it = memoryPool.begin(); it != memoryPool.end(); ++it)
{
/* ... */
}
return ret;
}
void operator delete(void* ptr) noexcept
{
for(auto it = memoryPool.begin(); it != memoryPool.end(); ++it)
{
/* ... */
}
}
};
おとぎ話の場合、MemoryPoolを使ったクラスの宣言は甘いでしょう。
class Interface
{/*...*/};
class Foo : public Interface, MemoryPool<Foo, 8>
{/*...*/};
class Bar : public Interface
{/*...*/};
とオブジェクトの宣言:
Foo* foo = new Foo(); // goes to dedicated memory pool
Bar* bar = new Bar(); // fails on build
しかしstatic std::array<uint8_t[sizeof(Pool)], size> memoryPool;
が静的であり、それはクラスのサイズは変更されませんので、クラスの外に行く場合でも、コンパイラはFoo
があると文句を言い不完全とFoo
src/metal/dynamic.hpp:14:24: error: invalid application of 'sizeof' to incomplete type 'Foo'
uint8_t memory[sizeof(T)] __attribute__ ((aligned (sizeof(void*))));
の大きさは、この「不完全型」小胞体を回避することが可能です推測することはできませんror?
解決策を完全に再設計する必要がありますか?
'class Foo'は完全に宣言されていないため不明な' class Interface'から継承しています。 'class Foo'を宣言する前に' class Interface'(メンバーで完全宣言)を宣言しようとしてください – nikniknik2016
@ nikniknik2016これは本当の問題ではありません。私の答えは –
@ nikniknik2016 m.sです。質問の目的のために、コードをあまりにも単純化します。 –