17

これは、Andrei Alexandrescuの投稿から着想を得ています。

次の方法で式を初期化することの長所と短所は何ですか? いつどちらを優先する必要がありますか?

auto v = expr;
T v = expr;
auto v(expr);
T v(expr);
auto v { expr }; 
T v {expr};
4

5 に答える 5

15
auto v = expr;
auto v(expr);

コード内で のタイプがわからず、exprジェネリックのままにしたい場合、またはコード内でタイプexprが何であるかが完全に明確であるため (上記の行の定義など)、auto混乱を招くことはありません。

初期化の形式は、括弧かどうかは関係ありません (微妙な違いがあるため、言語弁護士にのみ関連します)。より快適に感じるものを使用してください。


T v = expr;
T v(expr);

コード内で何exprが明確でない場合 (定義が離れすぎているなど)、または の型がわからないが型にexprなりたいv場合T。「expr」が持つ「種類の値」で作業を続けたい場合は、最初の形式を使用します (つまり、exprが文字列でT文字列型の場合)。Widgetまったく新しい種類の値 (つまり、 ,exprがウィジェットの色)を構築する場合は、2 番目の形式を使用します。


auto v { expr }; 

これを現在の C++ で使用しないでください (おそらく今後数年以内に)。であると宣言vしますstd::initializer_list<TypeOfExpr>。それが必要な場合は、型を直接使用して書き出します。これはあまりにも微妙です (そして、C++14 を超えてこの事実を変更する提案があるため、これを C++17 などで記述できることが期待されます)。


T v {expr};

縮小変換 (つまり、 から1000へのchar誤った変換) から身を守りたい場合、または初期化子リスト コンストラクターを持つクラスを初期化したい場合、または初期化するメンバーの集合体がある場合は、このフォームを使用してください。あるいは、イニシャライザ リスト コンストラクタ、集約型、または単純な非クラス型を扱う場合は、次を使用できます。

T v = { expr };

任意のコンストラクターの呼び出しには使用しません。そのために次のフォームを使用します

T v(expr);

ただし、そのためにブレース形式を使用することを好む人もいます. 私は自分のコードが何をしているのかを確実に知りたいので、コンストラクターを呼び出したいが、代わりに集計またはリストの初期化コンストラクター呼び出しをランダムに実行したくない場合は、中かっこの代わりに括弧を使用します。 

于 2013-09-11T20:05:47.523 に答える
5

auto v = expr; T v = expr;は問題ありませんが、auto 版では の型がわかりにくいかもしれませんexpr

たとえば、 では、 ??auto x = snafuscate();の型は何ですか?x

あいまいさが存在する場合は、右辺の型を次のように明示的に宣言することをお勧めします。auto x = Gadget { snafuscate() };

...

auto v(expr);Validは関数ポインタとしても理解できるため、 andT v(expr);は悪い考えです。expr

このコードはコンパイルされません:

int main()
{
    int x(int());
    return x + 3;
}

prog.cpp:4:11: error: invalid conversion from ‘int (*)(int (*)())’ to ‘int’ [-fpermissive]
return x + 3;
         ^

...

auto v { expr };v の型が T ではなく initializer_list になるため、ほとんどの場合間違っています。

自動のベスト プラクティスについては、http: //herbsutter.com/2013/08/12/gotw-94-solution-aaa-style-almost-always-auto/を参照してください。

于 2013-09-11T00:00:47.273 に答える
5

意味が異なる場合 (たとえばvector<int> v(12)、値が 12 のベクトルが得られない場合) を除いて、コンパイラは上記のすべてに対して同じ結果を返す必要があります。より良い"。

auto型の入力が難しく、型が文脈から明らかな場合に役立ちます。ただしauto x = 12;、署名されているか署名されていないかを判断するのは困難です。たとえば、[ルールがわかりません。おそらく署名されています]。

于 2013-09-11T00:01:14.400 に答える
2

auto を使う必要はないと思います

auto x = 12332; // or
auto z = 0xffff; //

なぜなら、

auto x = 12332; // type is  'int'
auto x2 = 0xffff // type is 'int'
auto y = 0xffffffff; // 8 fs,  type is unsigned int
auto z = 0xfffffffff;// 9 fs,  type is long long
auto t = 0xffffffffffffffff; // 16 fs, type is unsigned long long.

しかし、あなたは使うことができます

auto size = array.size();
于 2013-09-11T05:55:10.563 に答える
2

これはかなり難しい質問です。

2 つの異なる問題があります。

1 つ目は、型推論を使用するかどうか、つまり、auto指定子を使用するか、型を明示的に指定するかです。一般に、型が長くて扱いにくい場合 (イテレータなど) を除いて、読みやすくするために型を明示的に指定する方が良いと思います。

auto it = vec.begin();

または、型が初期化子から明らかな場合:

auto pfoo = new Foo(x,y,z);

または読みやすさを気にしない場合。

2 番目は、使用する初期化のタイプです。直接初期化、コピー初期化、およびリスト初期化があり、初期化の動作は宛先のタイプに大きく依存します。これらの違いは、C++ 標準のセクション 8.5 で説明されています。また、単純な宣言だけでなく、初期化もさまざまな場所で行われます。初期化は、パラメーターの受け渡し、戻り値、部分式、ステートメントの条件、配列の境界、およびその他多くの場所で行われます。これは実際に詳細を理解する必要があるものであり、短い要約では十分ではありません。

于 2013-09-11T07:35:59.247 に答える