()と{}初期化の使い方
初期化の方式を指定します.小かっこ、等号を使うか、大かっこを使うかを含みます.
int x(0); //
int y = 0; //
int z{
0}; //
int z = {
0}; //
多くの人が同じ番号で初期化文を書くのが好きで、初心者はこの中で一回の賦課が発生すると思っていますが、実際にはありません.私達はintなどの内型を使って区分する必要はありません.しかし、カスタム型を使う時は、区分して初期化と賦課の概念を初期化しなければなりません.Widget w1; //
Widget w2 = w1; // ,
w1 = w2; // ,
C++11 : 、 、 。 。
大かっこの初期化は、前には表現できなかったことを表すことができます.大かっこで容器の初期内容を指定するのは簡単です.
std::vector<int> v{
1,3,5}; //v 1,3,5
大括弧初期化は、非静的なメンバーにデフォルトの初期化値を指定することができ、C+11では「=」初期化文法を使用することもできますが、小かっこは使用できません.class Widget{
private:
int x{
0};
int y = 0;
//int z(0); //
};
コピーできないオブジェクトは、大かっこと小かっこで初期化できますが、「=」は使えません.std::atomic<int> ai1{
0};
std::atomic<int> ai2(0);
//std::atomic ai3 = 0; //
これらの3つの初期化方法の中で、大かっこ初期化方法だけがすべての場合に適用されることを示します.しかし、大かっこの初期化には新しい特性があります.これは内のパターン間の暗黙的狭窄型の転換を禁止します.大括弧内の表現が初期化されたオブジェクトを使用することが保証されていない場合、コードはコンパイルによって使用できませんが、小かっこと等号は可能です.
double x,y,z;
//int sum{x + y + z}; // ,double int
int sum2(x + y + z);
int sum3 = x+y+z;
大かっこ初期化の特徴の一つは、C++の最も悩ましい解析文法免疫である.C++は声明に解析できるものはすべて声明として解析し、副作用をもたらすと規定しています.プログラマはデフォルトでオブジェクトを作成しようとしましたが、誤って関数を宣言しました.このエラーの根本的な原因は構造関数が文法を呼び出すことにある.//
Widget w1(10); // Widget , 10
// Widget ,
Widget w2(); // w2, Widget
関数宣言は、大かっこで指定できませんので、大かっこを使ってオブジェクトのデフォルトの構造を完成するのは問題ありません.Widget w3{
}; //
大かっこの初期化にはいくつかの欠陥があり、大かっこの初期化に伴い、思いがけない行動が発生する場合があります.このような行為は、大括弧初期化物、std:initializer_から発生します.list及び構造関数再負荷決議の間の葛藤関係.これらの相互作用によってコードは何かをするように見えますが、実は別のことをしています.例えば、大括弧初期化物を使用してaut宣言を使用した変数を初期化すると、導き出すパターンがstd:initializer_リストコンストラクタが呼び出された時、形参にはstdが一つもない限り、:initializer_リストパターンは、小かっこと大かっこの意味が違います.一つ以上のコンストラクタがstdを備えていると宣言した場合:initializer_リスト型の他の形は、大括弧初期化文法を採用した呼び出し文が優先的にstdがあります:initializer_リストパターン別モダリティのリロードバージョン.通常はコピーや移動を行うコンストラクタでもstd:initializer_リスト型の他の形の構築関数ハイジャック:
// std::initializer_list ,
class Widget{
public:
Widget(int i,bool b);
Widget(int i,double d);
};
Widget w1(10,true); //
Widget w2{
10,true}; //
Widget w3(10,5.0); //
Widget w4{
10,5.0}; //
// std::initializer_list ,
class Widget{
public:
Widget(int i,bool b);
Widget(int i,double d);
Widget(std::intializer_list<long double> il);
operator float() const ; // float
};
Widget w1(10,true); //
Widget w2{
10,true}; // , ,10 true long double
Widget w3(10,5.0); //
Widget w4{
10,5.0}; // , ,10 5.0 long double
Widget w5(w4); // ,
Widget w6{
w4}; // ,
//w4 float, float long double
Widget w7(std::move(w4)); // ,
Widget w8{
std::move(w4)}; // , , w6
この優先的な呼び出しは非常に強く、最も好ましい呼び出しstd:initializer_リストのコンストラクタは起動できません.コンパイラはこれを選択します.大括弧の初期化物の中の実際の参をstdに転化する方法が見つからないだけです.リストテンプレートのパターンの場合、コンパイラは通常の負荷関数をチェックします.class Widget{
public:
Widget(int i,bool b);
Widget(int i,double d);
Widget(std::initializer_list<bool> il);
};
Widget w{
10,5.0}; // , 10 5.0 bool
class Widget{
public:
Widget(int i,bool b);
Widget(int i,double d);
Widget(std::initializer_list<std::string> il);
};
Widget w{
10,5.0}; // , int double string ,
stdに対して:initializer_リストにはもう一つの小さな問題があります.ペアの大きな括弧を使ってオブジェクトを作成します.このオブジェクトはデフォルトの構造にも対応しています.リストパターンパラメータの構造.この場合の対空大かっこは、「空のstd::initializercuulist」ではなく、「実参がない」という意味です.空のstd:initializer_リストは、空の大かっこを構造関数として使用することによって実現できます.つまり、一対の大かっこを小かっこまたは大かっこに入れます.class Widget{
public:
Widget(); //
Widget(std::initializer_list<int> il);
};
Widget w1; //
Widget w2{
}; //
Widget w3(); // ,
Widget w4({
}); // std::initializer_list , std::initializer_list
Widget w5{
{
}}; //
_; 大括弧初期化物、std:initializer_list、コンストラクタの重載決議は、これらの内容が不注意によって大きく影響されます.直接影響したのはstd:vector類です.std::vector類には一つの形参にstdがない:initializer_リストパターンの構築関数は、容器の初期サイズを指定し、初期化時にすべての要素が持つ値を指定することができます.でも、もう一つはstdを持っています.リスト型の他の形の構造関数により、容器の中の元素値を一つずつ指定することができます.私たちが数値型の要素を作成する場合:vectorは、2つの実際の参画構造関数を伝達すると、小かっこと大かっこの結果は大きく違ってきます.// , std::initializer_list
// 10 std::vector, 20
std::vector<int> v1(10,20);
// , std::initializer_list
// 2 std::vector, 10 20
std::vector<int> v2{
10,20};
ですから、ある程度はvectorのデザインに欠陥があります.私たちは自分でクラスを設計する時、自分で書いたリロード構造関数のセットの中にstdがある限り意識しなければなりません.リストイメージ参では、大括弧初期化を使用したクライアントコードは、これらの構造のリロードバージョンのみを発見することができる.