コンテンツにスキップ

最終更新:2026-10-12

C++20 [[no_unique_address]]

C++那些事によるメモリ最適化

プログラムの実行時、メモリは大きな問題になることが多く、メモリ占有量の削減とアクセス速度の向上は非常に重要です。これらの問題を解決するため、C++20 は no_unique_address 機能を導入し、空基底クラス最適化(EBO, Empty Base Optimization)と組み合わせることで、開発者にメモリレイアウトを最適化する効果的な方法を提供します。

1. 空基底クラス最適化(EBO)

EBO とは、空の基底クラス(データメンバを持たないクラス)が派生クラス内に存在しても余分なメモリを占有しないことを指します。C++ コンパイラはこれらの空基底クラスのインスタンスを統合し、不要なメモリオーバーヘッドを避けます。これは複雑なクラス階層を設計する際に特に有用で、オブジェクトのサイズを効果的に削減できます。

#include <iostream>
class Empty {};

class Derived : public Empty {
  int value;

 public:
  Derived(int v) : value(v) {}
};

class Test {
  int value;

 public:
  Test(int v) : value(v) {}
  Empty e;
};

int main() {
  std::cout << sizeof(Derived) << std::endl;
  std::cout << sizeof(Test) << std::endl;
  return 0;
}

上のコードでは、Derived クラスはメモリ上で int のサイズだけを占有し、int + Empty のサイズではありません。これはコンパイラが EBO の特性を利用しているためです。

さて、上のコードの出力がいくつになるか予想できますか?

2. no_unique_address 機能

C++20 で導入された no_unique_address 機能は、特定のクラスメンバを明示的にマークして、メモリ上で余分な空間を占有しないようにできます。<0バイトオブジェクト>に特に適しています。例えば:

unique_ptr で Deleter が空の構造体/クラスの場合、得られる sizeof は 16 ですが、C++20 以降はバイトを消費せず、全体の sizeof は 8 になります。

template<class T, class Deleter>
class unique_ptr {
    T* pointer = nullptr;
    [[no_unique_address]] Deleter deleter;

   public:
    // 其他成员函数...
};

本節終わり

関連トピック

コメント