5

代入以外で自動的に管理される単純な変数を初期化する場合、いくつかの異なるスタイルがあります。どちらか一方を優先する特定の理由があるのか​​ 、それとも単にスタイルの問題なのか疑問に思っていました.

オブジェクトのインスタンス化に似ているため、括弧の使用は魅力的です

double answer(42.0);
ComplexNumber i(0,1);

コンテナーの初期化に似ているため、ブレースの使用は魅力的です

double answer{42};
std::vector<double> i{0,1};
double i2[] = {0,1};

あるスタイルを他のスタイルよりも優先する特定の理由はありますか?

4

3 に答える 3

4

ここを見てください:GotW #1 : Variable Initialization。H. Sutter からの回答の詳細な説明です。

H. Sutter は上記で、変数の初期化の古いスタイルと新しいスタイルの一般的な意味で話しています。

以下は、開始トピックのコンテキストに従って、記事の簡単な概要を示しています。


このペア

double answer(42.0); // (1)
double answer{42};  // (2)

実際、次の初期化の例に似ています。

widget w(x);                // (d)
widget w{x};                // (e)

これらは両方とも直接初期化です。ただし、構文{x}によってinitializer_list. widgetを受け取るコンストラクターがある場合initializer_list、そのコンストラクターが優先されます。それ以外の場合、widget任意の型を取るコンストラクターがあるx場合 (おそらく変換あり)、そのコンストラクターが使用されます。

(2, e) を (1, d) よりも優れたものにする主な違いが 2 つあります。

  • まず、構文 (2, e) は明確であり、「厄介な解析」を回避します。xが型名の場合、(1, d) は、xスコープ内に名前が付けられた変数 (上記を参照) があっても関数宣言ですが、(2, e) は決して関数宣言ではありません。
  • 第 2 に、構文 (2, e) はより安全です。なぜなら、それ以外の場合は一部の組み込み型で許可される縮小 (別名「非可逆」) 変換が許可されないためです。検討:

    int i1( 12.345 ); // ok: toss .345, we didn't like it anyway

    int i2{ 12.345 }; // error: would be lossy implicit narrowing

次のペア

ComplexNumber i(0,1); // (3)
std::vector<double> i{0,1}; // (4)

複雑なオブジェクトの初期化に関連付けられています。どちらもまったく同じように見えますが、2 番目のものは、次のような「厄介な解析」を回避するのに役立ちます。

ComplexNumber       w( real(), img() );       // oops, vexing parse 

それに加えて、この方法はコードをより明確にし ( を使用するinitializer_listと、初期化であることがより明確になります)、さらに、場合によっては構文を緩和します。たとえば、次のようになります。

draw_rect({ origin, selection });                  // C++11

Sutter ギルドラインは次のとおりです。or{ }などの初期化を使用することを好みます。これは、より一貫性があり、より正確であり、古いスタイルの落とし穴について知る必要がまったくないためです。;のように、記号だけを表示したい単一引数の場合。そして; 中括弧を省略しても問題ありません。vector<int> v = { 1, 2, 3, 4 };auto v = vector<int>{ 1, 2, 3, 4 };=int i = 42auto x = anything

特別なコンストラクターの明示的な呼び出しに () 初期化を使用できます。

于 2013-06-14T16:12:00.073 に答える
2

Boris回答に加えて、Herb のブログ投稿には記載されていない別の落とし穴があります。

次のコードは違法です。

#include <initializer_list>

int main() {
  auto i{42}; // not the same as 'auto i(42);'
  ++i;
}

gcc 4.7.2 で発生するエラー メッセージは次のとおりです。

エラー: '++i' の 'operator++' に一致しません

その理由は、多くの人が信じているよりもむしろauto、 のタイプを推測するためです。forがないため、エラーが発生します。に置き換えると、コードは正常にコンパイルされます。{42}std::inilializer_list<int>intoperator ++std::initializer_list<int>{42}(42)

于 2013-06-14T16:41:20.343 に答える
1

GotW #93には、すべてを で宣言するための非常に興味深い理論的根拠がありautoます。

于 2013-06-14T16:39:13.567 に答える