この記事は初心者 C++er Advent Calendar 2015の3日目の記事です。


前回(統一初期化・リスト初期化の見本帳)、波括弧の初期化が使える場面を紹介しました。今回は、これがあって嬉しい事例を書いていきます。

波括弧の初期化が使える場面

というわけで、波括弧による初期化が便利な場面を3つ取り上げます。

関数宣言との混乱を避ける

波括弧の良いところの1つに、関数宣言との曖昧さが発生しないことがあります。{}を使うと、確実に変数定義になります。

「変数を定義したかったのに関数宣言になってしまう」という問題を回避できます。

#include <iostream>
#include <iterator>
#include <vector>
 
using namespace std;
 
int main()
{
  // これは関数宣言になってしまう。
  vector<int> v1(
    istream_iterator<int>(cin),
    istream_iterator<int>());
 
  // 昔からの回避策。
  vector<int> v2(
    (istream_iterator<int>(cin)),
    istream_iterator<int>());
 
  // これもOK。
  vector<int> v3{
    istream_iterator<int>(cin),
    istream_iterator<int>(),
  };
}

0初期化

ローカル変数などでは、int x;とすると、中にゴミが入っているのがよくあるC++コンパイラの実装です。実行速度最優先だからですね。

そうすると、0初期値してほしいときに困ります。「int x = 0;と書けばいいのでは?」というと、テンプレートで困ります。T x = T();と書けばよいかというと、それも微妙です。それだとコピーコンストラクタもムーブコンストラクタも無いクラスで使えなくなるので、可能なら避けたいのです。

というわけで、中身が空の{}による初期化です。

template<typename T>
T f(bool condition)
{
  T x{};
  if (condition)
  {
    // xに手を加える
  }
  return x;
}

これならTが組込型のintだろうとクラスだろうと大丈夫です。intなら0に初期化されますし、クラス型ならデフォルトコンストラクタが呼び出されます。

なお、Boostにvalue_initializedがあります(Let’s Boost value_initialized)。C++03では重宝しましたが、これでお役御免です。

仮引数・戻り値を直接構築する

波括弧を使わない書き方では、仮引数・戻り値のオブジェクトは実引数・reutrn文からのコピー初期化またはムーブ初期化になります。一方、波括弧を使うと、コピーやムーブではない直接の初期化が可能になります。

つまり、コピーもムーブもできないオブジェクトを引数・戻り値で扱えるようになるのです。

#include <mutex>
 
using namespace std;
 
void f(mutex);
 
int main()
{
  //f(mutex()); コンパイルエラー
  f({});
}
 
mutex g()
{
  // return mutex(); コンパイルエラー
  return {};
}

なお、コピー・ムーブ不可能な型を戻り値とする場合、受け取る側は一時オブジェクトへの参照として受け取る必要があります。

#include <mutex>
 
using namespace std;
 
void f0(mutex);
void f1(mutex&&);
void f2(const mutex&);
 
mutex g();
 
int main()
{
  // auto x = g(); コンパイルエラー
  auto&& y = g();
  const auto& z = g();
 
  // f0(g()); コンパイルエラー
  f1(g());
  f2(g());
}

ムーブ・コピー不可のクラスを戻り値の型にするコードの実例として、Boostのmake_lock_guard関数があります。

使うべきでない場面

ここまで、便利になる場合を紹介してきました。しかし、「すべて波括弧にするべきだ」というのは正解ではありません。

使える場面、使わないほうが良い場面については、C++11 Universal Initialization は、いつでも使うべきなのか – Qiitaに分かりやすくまとまっています。

まとめ

波括弧による初期化があると嬉しい場面を紹介しました。一方で、残念ながらなんでもかんでも波括弧にすれば良いというわけではありません。適材適所、上手に使いましょう。

スポンサード リンク

この記事のカテゴリ

  • ⇒ 波括弧の初期化があって嬉しいとき