質問
他人のコードを読んでいた時、構造体へ一度に初期化するコードを見かけました。それが以下のコードです。
C++
1#include <iostream> 2 3struct RGB { 4 int red, green, blue; 5}; 6 7int main() { 8 struct RGB cube1 = {1, 5, 6}; // 方法1 9 struct RGB cube2 = RGB{1, 5, 6}; // 方法2 10 11 return 0; 12}
そこで質問があります。構造体を初期化する際、{1, 5, 6}
で初期化する方法と、RGB{1, 5, 6}
で初期化する方法は、意味としては同じなのでしょうか?
cube1
とcube2
のメンバを表示した結果、ちゃんと初期化されていることは確認しました。しかし、方法1と方法2では書き方が違うので、本当に方法1と方法2が同じ意味なのか気になったので質問しました。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
![guest](/img/icon/icnUserSample.jpg)
回答3件
0
ベストアンサー
構造体を初期化する際、
{1, 5, 6}
で初期化する方法と、RGB{1, 5, 6}
で初期化する方法は、意味としては同じなのでしょうか?
同じ意味です。
(細かい仕様のお話;通常は気にしなくても良いです)
C++
1struct RGB cube1 = {1, 5, 6}; // 方法1 2struct RGB cube2 = RGB{1, 5, 6}; // 方法2
C++言語の構文上はそれぞれ 1) 変数cube1
のcopy-list-initialization、2) direct-list-initializationされた一時オブジェクトによる変数cube2
の初期化になります。最新のC++仕様(C++17)では、1)/2)は同一の振る舞いになることが保証されます。過去バージョン(C++11~C++14)でも、実用上は1/2)の書き方で差異はありません。もっと古いバージョン(C++03以前)では、2)の書き方がコンパイルエラーになります。
投稿2018/01/30 02:26
総合スコア6191
0
ええっとC++に構造体はないのでクラスですね。
cpp
1RGB cube1 = {1, 5, 6}; // 方法1 2RGB cube2 = RGB{1, 5, 6}; // 方法2
この2つですが、今回は特殊な条件に当てはまるので得られる結果は同じとなりますが、C++規格的にはべつのものです。
C++のクラスにはコンストラクタや代入演算子と言った特殊なメンバ関数があり、ある特定の条件を満たすとこれらの一部ないし全てが自動で生成されます。その条件は複雑ですが、その説明は
C++入門者に贈るclass入門とclass/structキーワードの使い分け - Qiita#コンパイラによる暗黙宣言
に丸投げするとして、結論から言うと今回のRGB
クラスは条件を満たしているのですべての特殊なメンバ関数が自動生成されます。
さて、方法1ですが、これはaggregate初期化です。コンストラクタによっては同様の記法でinitizer_listによる初期化とみなされることもあるからややこしい。
方法2も方法1と同じですが、ただし初期化したオブジェクト(RGB{1, 5, 6}
)をmoveして初期化しています(自信ない、C++17でRVO強制になったけどこれどう解釈されるんだ?1と完全同一になるのか・・・?)
追記
yohhoyさんの回答が正しいのでそれを見てください。
この2つですが、今回は特殊な条件に当てはまるので得られる結果は同じとなりますが、C++規格的にはべつのものです。
と言ったのは、例えば
std::vector<int> a1 = { 1, 2, 3 }; std::vector<int> a2 = std::vector<int>{ 1, 2, 3 };
この2つは(C++14までだと)違う挙動だよ、という意味合いの話でした。見かけ上すっごい似ていますよね?
C++17からはこれも同一の挙動になったはずなので、わかりやすくなった・・・のか?
投稿2018/01/29 17:18
編集2018/01/30 02:46総合スコア5852
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/01/31 07:09
![guest](/img/icon/icnUserSample.jpg)
0
意味としては同じなのでしょうか?
意味としては「違う」ものとなります。
cube1
の方は、RGB構造体を既定のコンストラクタRGB(int a, int b, int c)
で初期化するものです。既定のコンストラクタとは、コンストラクタの記述がない構造体(クラスも同様)で自動生成されるもので、この場合は単純にメンバ変数に値を設定します。
cube2
の方は、まず既定のコンストラクタRGB(int a, int b, int c)
で初期化した一時オブジェクトを生成し、それを既定のコピーコンストラクタでcube2
にコピーします。
つまり、結果は同じですが挙動は若干異なります。cube2
の方は、別にオブジェクトを作ってコピーするという手間が入る分、場合によってはわずかに遅くなります(ほとんどの場合無視できる程度ですが)。
初期化構文にはもう一つあります。
C++
1RGB cube3{1, 5, 6};
これは、意味としては方法1と同じです。というか、C++11で初期化リストの構文を拡張してこのような書き方が可能になりました。これによって方法2の書き方も可能になったわけです。
ちなみに、C++では構造体名(クラスも同様)は型名としても認識されるので、RGB
の手前にstruct
を付ける必要はありません。
投稿2018/01/30 02:06
総合スコア5938
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/01/30 02:30
![guest](/img/icon/icnUserSample.jpg)
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/01/30 12:42
2018/01/30 16:28
2018/01/31 04:01
2018/01/31 07:22 編集