質問
他人のコードを読んでいた時、構造体へ一度に初期化するコードを見かけました。それが以下のコードです。
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が同じ意味なのか気になったので質問しました。
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
下記のような質問は推奨されていません。
- 質問になっていない投稿
- スパムや攻撃的な表現を用いた投稿
適切な質問に修正を依頼しましょう。
回答3件
5
ベストアンサー
構造体を初期化する際、
{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
総合スコア6181
1
ええっと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総合スコア5850
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
回答へのコメント
2018/01/31 07:09
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
総合スコア5936
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
回答へのコメント
2018/01/30 02:30
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
関連した質問
意見交換
受付中
メンバ関数の呼び出し方について
回答4
クリップ0
更新
2023/05/24
Q&A
解決済
【Java】Arraysクラスのインスタンス生成ができない理由について
回答2
クリップ0
更新
2023/05/21
Q&A
受付中
「リスコフの置換原則」はインターフェースでも適用されますか?
回答2
クリップ0
更新
2023/05/23
意見交換
受付中
MySQL カラムで真偽値の扱いについて、BIT(1) か BOOLEAN か?
回答20
クリップ0
更新
2023/05/16
Q&A
解決済
OpenCVで画像の輪郭の複雑さを数値化したいです。
回答3
クリップ0
更新
2023/05/27
意見交換
受付中
Wordpressのphpファイルにデータベースの接続情報を直接記入しても大丈夫なのでしょうか。
回答39
クリップ2
更新
2023/05/25
意見交換
受付中
二次元配列の中身の後ろに空白を入れるけど末尾だけは空白をつけずに改行を出力する問題
回答18
クリップ1
更新
2023/05/26
意見交換
受付中
データ分析、機械学習や人工知能にPythonが使われている理由に関して。
回答7
クリップ2
更新
2023/05/28
同じタグがついた質問を見る
C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。
下記のような回答は推奨されていません。
このような回答には修正を依頼しましょう。
2018/01/30 12:42
2018/01/30 16:28
2018/01/31 04:01
2018/01/31 07:22 編集