質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

4341閲覧

リスト初期化について

JADEN

総合スコア106

C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

3グッド

1クリップ

投稿2016/03/06 09:07

リスト初期化において、以下のことを教えてください。
引用サイト: C++11: Syntax and Feature

  1. 2種類の直接初期化は、全く同じ意味か。

C++

1T x( { } ) ; // 直接初期化 2T x{ } ; // 直接初期化
  1. 直接初期化とコピー初期化の違いは何か。

C++

1T x( { } ) ; // 直接初期化 2T x{ } ; // 直接初期化 3T x = { } ; // コピー初期化
  1. コピーコンストラクタが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}
raccy, argius👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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};cinitvoid (int)
CBase base12{1};listinitvoid (int)
CBase base13({1});callinitvoid (int)
CBase base14(1);callinitvoid (int)
CBase base15 = CBase(1);cintvoid (class CBase &&)
CBase base21 = {1, 2};cintvoid (ini, int)
CBase base22{1, 2};listinitvoid (int, int)
CBase base23({1, 2});callinitvoid (class CBase &&)
CBase base24(1, 2);callinitvoid (int, int)
CBase base25 = CBase(1, 2);cintvoid (class CBase &&)

cintとlistintとcallintは書き方が違うだけで、コンパイルでの処理は全く一緒です。つまり、1)と2)は基本的には一緒で、違いはありません。3)でコンパイルが通るのは、そもそもコピーコンストラクタを使ってないからです。

さて、問題はbase23です。CBase base23({1, 2});と要素が2個になるとムーブコンストラクタに変わってしまいます。一個の時となぜ違うかというと、**すいません、わかりませんでした。**誰か答えてくれるのを私も待ちます。

投稿2016/03/07 11:09

raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/03/07 13:09

こんな風に初期化の過程観れるんですね。勉強になります。これは恐らく{}の要素が一個の時はint型で解釈されて,複数個ある時は,std::initializer_list<int>型で解釈されるため引数std::initializer_list<int>型のコンストラクタを生成していないからではないでしょうか。
yohhoy

2016/03/07 14:01 編集

その方法で確認できるのはプレーンなASTなので、実際にはRVO(copy elide)が有効ならばbase15は1要素コンストラク呼び出しへ、base23とbase25は2要素コンストラクタ呼び出しに最適化されると思います。 http://melpon.org/wandbox/permlink/kIjNjc4W9kLIIdb9 (オプション -fno-elide-constructors を外してみてください)
JADEN

2016/03/08 13:30 編集

回答ありがとうございます。
JADEN

2016/03/08 13:29

例えば、CBase base15 = CBase(1); の結果で、ムーブコンストラクタが呼ばれます。 右辺値はconst CBase&でも保持できるため、コピーコンストラクタとムーブコンストラクタのオーバーロードになると思いますが、ムーブコンストラクタが呼び出されるのは仕様でしょうか?
raccy

2016/03/08 21:44

ムーブコンストラクタがよばれるのは、`CBase(1)`がrvalueだからです。 参考: http://qiita.com/you_aizawa/items/8a26c29b8faf9e6172a8 ただ、yohhoyさんの言うとおり、最適化で普通のコンストラクタになっちゃうようですね。うーん、難しい。
JADEN

2016/03/09 11:40

右辺値はconst&でも受け取れるので、オーバーロードに優先順位が決められていないと、どちらに渡してよいかコンパイラが判断できなくないですか?
raccy

2016/03/09 13:41

ムーブコンストラクタとコピーコンストラクタ両方が提供されている場合、渡す値がrvalueならばムーブコンストラクタが優先されるそうです。英語ですが、 http://en.cppreference.com/w/cpp/language/move_constructor のNotesの二段落目を参考にして下さい。
guest

0

ベストアンサー

  1. 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
  1. 直接初期化とコピー初期化の違いは何か。

コンストラクタが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
  1. コピーコンストラクタが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
yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

JADEN

2016/03/11 13:26 編集

回答ありがとうございます。 Effective Modern C++の44ページに、x{}とx={}の違いはないと書いてありますが、ユーザー定義型においては、やはりexplicitに関する違いがあると考えて良いということになりますね。
yohhoy

2016/03/11 14:26

日本語版では「Effective Modern C++の44ページに、x{}とx={}の違いはないと書いてあり」を見つけられなかったのですが、英語版でしょうか?
JADEN

2016/03/12 02:55 編集

日本語版44ページの一番最初の文です。 等号と波括弧の併用は、波括弧と同じとあります。
guest

0

1.全く同じものです。

2番の項目をraccyさんの結果をみて修正しました。僕の理解も浅かったようで申し訳なかったです。

2.raccyさんの言う通りコンストラクタの引数の指定の仕方に名称がついているだけで,実態は全て同じもののようです。指定した引数に当てはまるコンストラクタの呼び出しを行うという話で,コピーコンストラクタ等の話は関係ありませんでした。(なので=演算子の対象が{}型(void型) ,CBass& 型で呼び出されるコンストラクタが変わってるのは納得できると思います。)

3. 代入している値がCBaseクラス型じゃないからだと思います。検証したい場合はそれぞれのコンストラクターで標準出力で文字列などを出力してみるといいと思います。

投稿2016/03/07 08:02

編集2016/03/08 17:32
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

JADEN

2016/03/09 11:41 編集

回答ありがとうございます。 2.に関してです。 CBase base = CBase(); が、コピーコンストラクタを呼び出すことは分かります。 CBase base = {}; は、コピーコンストラクタがdeleteでもエラーにならないため(CBase base = CBase() は、コピーコンストラクタがdeleteだとエラー)、CBase base = CBase();とは異なると思いますが、いかがでしょうか。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問