Effective Modern C++を読んでいたら、スマートポインタというのを見つけた。正直、何者なのか知らなかったので調査してみると、 メモリリークなどの誤動作を防ぐためのポインタ機構らしい。 例えば、スマートポインタを使うとdeleteが不要になったり、例外を考慮する必要が無くなる。
Effective Modern C++ ―C++11/14プログラムを進化させる42項目
- 作者: Scott Meyers,千住治郎
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/09/18
- メディア: 大型本
- この商品を含むブログ (5件) を見る
そこで、試しにスマートポインタの勉強のために、ISSの一部にスマートポインタを導入してみた。
CMakeを使って、C++11をビルドできるようにする
gccでC++11のオプションが利用できるように、以下をCMakeLists.txtに加えた。
add_definitions("-std=c++0x")
スマートポインタを使って、ISSのメモリを確保する。
ISSでは、メモリアクセスを発生させる前にメモリを探索し、既にその領域が確保されていればそのまま参照、そうでなければ領域を新規作成する。 このルーチンをスマートポインタで置き換えてみる。
MemResult Memory::InsertMemTable (Addr_t addr, Word_t data) { // at first, traverse memory table and check memory region is already registered or not std::map<Addr_t, std::unique_ptr<MemoryBlock>>::iterator it; Addr_t baseaddr = addr & 0xFFFFF000ULL; if ((it = m_memory_vec.find (baseaddr)) != m_memory_vec.end()) { it->second->WriteByte (addr - baseaddr, static_cast<Byte_t>(data)); return MemNoExcept; } std::unique_ptr<MemoryBlock> memory_block (new MemoryBlock (baseaddr, 0x1000ULL, 0x7)); memory_block->WriteByte (addr - baseaddr, static_cast<Byte_t>(data)); m_memory_vec.insert (std::make_pair(baseaddr, std::move(memory_block))); return MemNewRegion; }
まずはイテレータを作成し、マップの中を、当該アドレスの領域が存在するかを探索している。 スマートポインタに対するマップは同様に作成することができ、探索にはfindを使っている。
次に、メモリアドレスが存在しない場合は、まずはstd::unique_ptrのスマートポインタを作成し、新しくMemoryBlockクラスをインスタンスする。 マップに挿入するときは、make_pairでペアを生成するのだが、その際にポインタの権限を移譲するために、std::moveを使ってstd::mapに挿入している。
これ、その前のWriteByteのメソッドが存在しなければ、
m_memory_vec.insert (std::make_pair(baseaddr, std::unique_ptr<MemoryBlock> (new MemoryBlock (baseaddr, 0x1000ULL, 0x7)));
でも良いみたいなのだが、一度作成したインスタンスで処理を行う必要があるため、今回はstd::moveを使っている。