リスト初期化において、以下のことを教えてください。
引用サイト: C++11: Syntax and Feature
- 2種類の直接初期化は、全く同じ意味か。
C++
1T x( { } ) ; // 直接初期化 2T x{ } ; // 直接初期化
- 直接初期化とコピー初期化の違いは何か。
C++
1T x( { } ) ; // 直接初期化 2T x{ } ; // 直接初期化 3T x = { } ; // コピー初期化
- コピーコンストラクタがdeleteなのに、なぜ以下のコードが通るのか。
C++
1// コンパイラ: MSVC 2class CBase { 3public: 4 CBase() = default; 5 CBase(int data) : m_data{data} {}; 6 CBase(const CBase& base) = delete; 7 int m_data = 0; 8}; 9int main() { 10 CBase base = {1}; 11}
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
Clangを用いて、clang++ -Xclang -ast-dump -fsyntax-only -std=c++14 《C++ファイル》
でどのように解釈されるかを確認しました。検証用はコンストラクタの削除等は消して、引数2個のコンストラクタを追加しています。
C++
1class CBase 2{ 3 public: 4 CBase(int data) : m_data{data} {}; 5 CBase(int data, int dummy) : m_data{data} {}; 6 int m_data = 0; 7}; 8int main() 9{ 10 CBase base11 = {1}; 11 CBase base12{1}; 12 CBase base13({1}); 13 CBase base14(1); 14 CBase base15 = CBase(1); 15 CBase base21 = {1, 2}; 16 CBase base22{1, 2}; 17 CBase base23({1, 2}); 18 CBase base24(1, 2); 19 CBase base25 = CBase(1, 2); 20}
初期化 | VerDeclスタイル | コンストラクタ |
---|---|---|
CBase base11 = {1}; | cinit | void (int) |
CBase base12{1}; | listinit | void (int) |
CBase base13({1}); | callinit | void (int) |
CBase base14(1); | callinit | void (int) |
CBase base15 = CBase(1); | cint | void (class CBase &&) |
CBase base21 = {1, 2}; | cint | void (ini, int) |
CBase base22{1, 2}; | listinit | void (int, int) |
CBase base23({1, 2}); | callinit | void (class CBase &&) |
CBase base24(1, 2); | callinit | void (int, int) |
CBase base25 = CBase(1, 2); | cint | void (class CBase &&) |
cintとlistintとcallintは書き方が違うだけで、コンパイルでの処理は全く一緒です。つまり、1)と2)は基本的には一緒で、違いはありません。3)でコンパイルが通るのは、そもそもコピーコンストラクタを使ってないからです。
さて、問題はbase23です。CBase base23({1, 2});
と要素が2個になるとムーブコンストラクタに変わってしまいます。一個の時となぜ違うかというと、**すいません、わかりませんでした。**誰か答えてくれるのを私も待ちます。
投稿2016/03/07 11:09
総合スコア21735
0
ベストアンサー
- 2種類の直接初期化は、全く同じ意味か。
どちらも直接リスト初期化(direct-list-initialization)であり、コンパイラにとっては同義です。
ただし、前者の書き方では警告を引き起こすこともあります。
C++
1struct X { 2 X(int v) : m{v} {} 3 int m; 4}; 5 6X x1({42}); // warning: braces around scalar initializer [-Wbraced-scalar-init] 7X x2{42}; // OK
- 直接初期化とコピー初期化の違いは何か。
コンストラクタがexplicit
修飾されているとき、両初期化の違いがあらわれます。直接初期化はexplicit
コンストラクタでも大丈夫ですが、コピー初期化はコンパイルエラーを引き起こします。
struct Y { explicit Y(int v) : m{v} {} int m; }; Y y1{42}; // OK Y y2 = {42}; // error: chosen constructor is explicit in copy-initialization
- コピーコンストラクタがdeleteなのに、なぜ以下のコードが通るのか。
この書き方での初期化では、コピーコンストラクタを要求せず、普通のコンストラクタを直接呼び出します。ただし2)の通り、explicit
修飾なしコンストラクタを要求します。
C++
1struct Z1 { 2 Z1(int) {} // 非explicit 3 Z1(const Z1&) = delete; 4}; 5 6struct Z2 { 7 Z2(int, int) {} // 非explicit 8 Z2(const Z2&) = delete; 9}; 10 11Z1 z1 = {1}; // OK 12Z2 z2 = {1, 2}; // OK
C++14仕様の§12.6.1 Explicit initialization [class.expl.init]/paragraph 1より引用:
An object of class type can be initialized with a parenthesized expression-list, where the expression-list is construed as an argument list for a constructor that is called to initialize the object. Alternatively, a single assignment-expression can be specified as an initializer using the
=
form of initialization. Either direct-initialization semantics or copy-initialization semantics apply; see 8.5.
投稿2016/03/10 12:14
編集2016/03/10 12:16総合スコア6191
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
1.全く同じものです。
2番の項目をraccyさんの結果をみて修正しました。僕の理解も浅かったようで申し訳なかったです。
2.raccyさんの言う通りコンストラクタの引数の指定の仕方に名称がついているだけで,実態は全て同じもののようです。指定した引数に当てはまるコンストラクタの呼び出しを行うという話で,コピーコンストラクタ等の話は関係ありませんでした。(なので=演算子の対象が{}型(void型) ,CBass& 型で呼び出されるコンストラクタが変わってるのは納得できると思います。)
3. 代入している値がCBaseクラス型じゃないからだと思います。検証したい場合はそれぞれのコンストラクターで標準出力で文字列などを出力してみるといいと思います。
投稿2016/03/07 08:02
編集2016/03/08 17:32退会済みユーザー
総合スコア0
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2016/03/07 13:09
2016/03/07 14:01 編集
2016/03/08 13:30 編集
2016/03/08 13:29
2016/03/08 21:44
2016/03/09 11:40
2016/03/09 13:41