はじめに
C++でパフォーマンスを意識したプログラミングや、ハードウェアに近い低レベルなデータ操作を行う際、オブジェクトがメモリ上で「どれくらいの領域を占めるか(サイズ)」や、「どのようなアドレスに配置されるべきか(アライメント)」を正確に知る必要があります。
この記事では、C++でサイズとアライメントを扱うための主要なキーワードを解説します。
1. sizeof
演算子: サイズを求める
sizeof
は、特定の型または変数が、メモリ上で占めるサイズをバイト単位で返します。
サンプルコード
#include <iostream>
struct MyData {
int id; // 4バイト (環境による)
double value; // 8バイト (環境による)
};
int main() {
std::cout << "--- 型のサイズ ---" << std::endl;
std::cout << "sizeof(char): " << sizeof(char) << std::endl;
std::cout << "sizeof(int): " << sizeof(int) << std::endl;
std::cout << "sizeof(double): " << sizeof(double) << std::endl;
std::cout << "sizeof(MyData): " << sizeof(MyData) << std::endl;
std::cout << "\n--- 変数のサイズ ---" << std::endl;
MyData data_object;
std::cout << "sizeof(data_object): " << sizeof(data_object) << std::endl;
return 0;
}
解説: sizeof
はコンパイル時に評価される演算子です。構造体のサイズは、メンバの合計サイズに、アライメントのためのパディング(詰め物)バイトが加わることがあります。
2. sizeof...
演算子: 可変長テンプレートの要素数を求める
sizeof...
は、C++11の可変長引数テンプレートで使われ、テンプレートパラメータパックに含まれる要素の数を返します。
サンプルコード
#include <iostream>
template<typename... Args>
struct CountTypes {
static const size_t count = sizeof...(Args);
};
int main() {
std::cout << "S<int, char, double> の要素数: "
<< CountTypes<int, char, double>::count << std::endl; // -> 3
std::cout << "S<> の要素数: "
<< CountTypes<>::count << std::endl; // -> 0
return 0;
}
3. alignof
演算子: アライメントを求める
alignof
(C++11) は、特定の型がメモリ上に配置される際に要求されるアライメントをバイト単位で返します。アライメントとは、オブジェクトを特定のバイト境界(例: 4バイトや8バイトの倍数のアドレス)に配置するという、CPUのパフォーマンス上の要求です。
サンプルコード
#include <iostream>
struct alignas(8) AlignedData { // アライメントを8バイトに指定
char data[3];
};
int main() {
std::cout << "alignof(char): " << alignof(char) << std::endl;
std::cout << "alignof(int): " << alignof(int) << std::endl;
std::cout << "alignof(double): " << alignof(double) << std::endl;
std::cout << "alignof(AlignedData): " << alignof(AlignedData) << std::endl; // -> 8
return 0;
}
4. alignas
指定子: アライメントを指定する
alignas
(C++11) は、変数やクラス/構造体のアライメントを、通常要求される値よりも厳しく指定するための指定子です。特定のメモリアライメントを要求するSIMD命令やハードウェアと連携する際に使われます。
サンプルコード
#include <iostream>
// この構造体のアライメントを32バイト境界に強制する
struct alignas(32) VectorData {
float x, y, z, w;
};
int main() {
VectorData v;
std::cout << "VectorDataのアライメント: " << alignof(VectorData) << std::endl; // -> 32
return 0;
}
まとめ
今回は、C++でメモリ上のサイズとアライメントを扱うためのキーワード群を解説しました。
sizeof
: 型や変数のサイズをバイト単位で取得する。sizeof...
: 可変長引数テンプレートの要素数を取得する。alignof
: 型が要求するアライメントをバイト単位で取得する。alignas
: 型のアライメントをより厳しく指定する。
これらの機能は、一般的なアプリケーション開発ではあまり意識することはありませんが、パフォーマンスの最適化や、ハードウェアに近い低レベルなプログラミングを行う際には不可欠な知識となります。