Posts
C++ で型推論 (auto) を使う際の注意点
C++11 で追加された型推論 (auto) を使うと長ったらしい iterator 宣言などを簡潔に書けることもあり、何でもかんでも auto で宣言したくなってしまうが、場面によっては今まで通りの型宣言をした方が良いケースもある。
数値
int や double など数値系の型は他の型と違い加算や減算が頻繁に行われるため、その際に発生した暗黙の型変換によってサイズや符号が変化し、いつの間にか意図しない型になっていることがある。
unsigned int uFoo = 1; int nBar = 2; int nSum = uFoo + nBar; // int auto nAutoSum = uFoo + nBar; // unsigned int
明示的な型宣言をしているコードを auto に置き換えるときは特に注意が必要。
ポインター
const と auto を組み合わせた時の挙動は少々特殊で、ポインターを const で宣言しても const になっていないことがある。
int nFoo = 1; const int* lpFoo = &nFoo; // const int* *lpFoo = 2; // エラー: 参照先が const なので書き込めない const auto lpAutoFoo = &nFoo; // int* const *lpAutoFoo = 2; // OK: const なのはアドレスなので書き込める
宣言を const auto* にすれば意図した結果になる。
const auto* lpAutoFoo = &nFoo; // const int*
これは非 const 値を const に変換するときに発生する問題なので、元の型宣言に const が含まれていれば auto だけでも問題ない。
const char* GetFoo() { return "Foo"; } auto lpszFoo = GetFoo(); // const char*
typedef
Visual Studio には変数の上にマウスカーソルを移動すると型情報を表示する機能があるので、auto を使う際にはこの機能を使って推論された型を確認しているが、typedef で宣言された型は typedef 名ではなく実際の型が表示されるため、元の型が何だったのか分からなくなることがある。
DWORD dwFoo = 1; // DWORD auto dwAutoFoo = dwFoo; // unsigned long
特に Win32 API は typedef を使った型が多いのでむやみに使わない方がいいかもしれない。