直接初期化
定義
- 明示的なコンストラクター引数のセットからオブジェクトを初期化します
文法
次の状況で直接初期化を実行します。
空でない括弧で囲まれた式のリストまたは中括弧の初期化子リストで初期化します(C ++ 11以降)
T object ( arg );
T object ( arg1, arg2, ... );
リストの初期化の一環として、中括弧で囲まれた単一の初期化子を使用して非クラス型および非配列型のオブジェクトを初期化する場合は、初期化子を提供する要素を初期化します(注:中括弧の初期化子リストを使用するクラス型およびその他の初期化の場合) 、参照
列表初始化
)(C ++ 11以降)
T object {
arg };
関数変換を使用するか、括弧で囲まれた式リストを使用して、一時的な純粋な右辺値を初期化します(C ++ 17より前)純粋な右辺値の結果オブジェクト(C ++ 17以降)
T ( other )
T ( arg1, arg2, ... )
static_cast式を使用して、純粋な右辺値を一時的に(C ++ 17より前に)純粋な右辺値の結果オブジェクトを初期化します(C ++ 17以降)
static_cast< T >( other )
空でない初期化子で新しい式を使用して、動的ストレージ期間を決定するオブジェクトを初期化します
new T(args, ...)
コンストラクタ初期化子リストを使用して基本クラスまたは非静的メンバーを初期化します
Class::Class() : member(args, ...) {
... }
ラムダ式のコピーによってキャプチャされた変数からクロージャオブジェクトのメンバーを初期化します
[arg](){
... }
直接初期化VSコピー初期化
入門書のステートメント
- クラス型オブジェクトとして使用する場合、初期化のコピー形式は直接形式とは異なります。
- 実際のパラメーターに一致するコンストラクターを直接初期化して直接呼び出す
- コピーの初期化は常に代入コンストラクターを呼び出します
- コピーの初期化では、最初にコンストラクターを使用して一時オブジェクトを作成し、次にコピーコンストラクターを使用してその一時オブジェクトを作成中のオブジェクトにコピーします。
- 通常、直接初期化とコピー初期化は、低レベルの最適化でのみ異なります。ただし、コピーをサポートしない型の場合、または非明示的なコンストラクターを使用する場合は、基本的に異なります。
#include <iostream>
#include <fstream>
using namespace std;
int main(){
ifstream file1("filename");//ok:direct initialization
ifstream file2 = "filename";//error:copy constructor is private”
}
よくある誤解
上記のステートメントから、次のことがわかります。直接初期化は必ずしもコピーコンストラクターを呼び出す必要はなく、コピー初期化はコピーコンストラクターを呼び出す必要があります。
ただし、ほとんどの人は、直接初期化はオブジェクトの構築時にコピーコンストラクターを呼び出すことであり、コピー初期化はオブジェクトの構築時に代入演算関数を呼び出すことであると考えています。初期化はオブジェクトの作成時にのみ発生するため、これは実際には大きな誤解です。。割り当て操作は、オブジェクトの作成プロセスには適用されません。この誤解が発生する理由については、コピーの初期化で等号(=)が原因である可能性があります。
例を見てみましょう
string str1 = "first"; //拷贝初始化,编译器允许把这句话改写为string str(“first”),但是string类必须有public的拷贝(移动)构造函数
string str2(10,'a'); //直接初始化
string str3(str2); //直接初始化
string str4 = string(10,'b'); //拷贝初始化
string str5 = str4; //拷贝初始化
string str6 ("strr"); //直接初始化
コピーコンストラクターの呼び出しがコピーの初期化であると誤解している場合、str3もコピーの初期化であると考えるかもしれませんが、これは間違っています〜
直接初期化:
- 通常の関数マッチングを使用して実行できる初期化は、直接初期化と呼ばれます。
- つまり、クラスのコンストラクターまたはコピーコンストラクターを直接呼び出すだけで初期化を完了できます。
- また、str2とstr3はそれぞれコンストラクターとコピーコンストラクターを呼び出すため、直接初期化されます。
コピーの初期化:
- オブジェクトを作成中のオブジェクトにコピーし、必要に応じて型変換を実行します。
- もちろん、これがコピーコンストラクターへの間接呼び出しです。ほとんどの場合、コピーコンストラクターが呼び出され、移動コンストラクターが呼び出されることもあります。
上記の例に基づいて、等号「=」が表示された場合にのみ、コピーの初期化になると考えることができます。
実際、それ以外の場合、コピーの初期化は次の3つの場合にも発生します。
- オブジェクトを実際のパラメーターとして非参照型の実際のパラメーターに渡します(参照がパラメーターとして使用されている場合はコピー操作を省略できるため、コードを最適化するために使用できる場合があります)
- 戻り値の型が非参照である関数からオブジェクトを返します
- 中括弧は、配列の要素または集約クラスのメンバーを初期化します(構造体)
例を見ています