2017-08-27 8 views
0

C++標準によれば、それが参照するオブジェクトを初期化する前に参照をコピーすることは未定義の動作ですか?次の例では、親クラスへの参照を渡し、親コンストラクタへの呼び出しがイニシャライザリストの最初になければならないため、オブジェクトの値を初期化します。ここで初期化されていないオブジェクトへの参照をC++でコピーする

#include <iostream> 

struct Object 
{ 
    int val; 
    Object(int i): val(i) {} 
}; 

struct Parent 
{ 
    Object& ref; 
    Parent(Object& i): ref(i){} 
}; 

struct Child : Parent 
{ 
    Object obj; 
    Child(int i): Parent(obj), obj(i) {} 
}; 

int main() 
{ 
    std::cout << Child(3).ref.val; 
} 

が親(OBJ)で初期化され、OBJの値が初期化されていません。

これはgccでうまくコンパイルされていますが、正しい出力が得られますが、標準または優れたコーディング慣行がそれに対してアドバイスしているかどうかはわかりません。それは未定義の動作ですか?もしそうでなければ、避けなければならない悪い習慣ですか?

+2

初期化されていない参照はありませんが、初期化されていないオブジェクトへの参照はありません。これは、標準から引用した場合とは異なります。すべてが初期化されるまで、 'Parent'が参照を使用しない限り、コードは正常です。 –

+0

ありがとう、あなたの発言を反映するためにタイトルを更新しました。あなたが言うことは、初期化されていないオブジェクトへのポインタで何が起きるかという意味で意味があります。 – Flynsee

+0

ボスのコメントはあなたの質問に答えましたか?または、あなたが尋ねたことの違いを明確にするために編集しましたか? – Yunnosch

答えて

2

まず、1つのことを明確にしましょう。 文字通り参照をコピーすることも可能かどうかわからない

int i = 10; 
int& ref = i;  // since this moment ref becomes "untouchable" 
int& alt_ref = ref; // actually, means int& alt_ref = i; 

私はrefは、いくつかのクラスのメンバーであり、あなたは、このクラスのインスタンスをコピーする場合、同じ問題が発生したと思います。 さらに、コードをもっと見ると、「参照をコピーする」ことさえできず、初期化されていない(まだ)オブジェクトの参照を初期化することはありません。

struct Parent 
{ 
    Object& ref; 
    Parent(Object& i): ref(i) { } 
}; 

struct Child : Parent 
{ 
    Object obj; 
    Child(int i): Parent(obj), obj(i) { } 
}; 

が物理的に等価である:それは言われていると

struct Child 
{ 
    Object& ref; 
    Object obj; 
    Child(int i): ref(obj), obj(i) { } 
}; 

、あなたの質問は、実際には意味:

はそれがに未定義の動作であるオブジェクトを初期化する 前の基準を初期化しますそれはを参照していますか?

同様に、オブジェクトのライフタイムが開始された前しかし後:ここ

は、C++標準からの引用である(§3.8.6[basic.life/6])、おそらく答えを与えますオブジェクトが占有するストレージが割り当てられているか、またはオブジェクトの寿命が終了した後で、オブジェクトが占有したストレージが再利用または解放される前に、 オリジナルオブジェクトを参照するglvalueが使用されます限られた方法で構築または破壊中のオブジェクト については、12.7を参照してください。そうでない場合、そのようなglvalue は、割り当てられたストレージ(3.7.4.2)を参照し、その値に依存しないgl値のプロパティを使用すると、明確に定義されます。

そして§12.7.1[class.cdtor/1]だけ書かれています:

...コンストラクタは、実行結果を開始する前に、オブジェクト のいずれかの非静的メンバまたは基本クラスを参照未定義の振る舞いでしたがって、「オブジェクト自体を参照」、「オブジェクトのメンバを参照し、」のみ言及§12.7.1

は§3.8.6に該当します。 このようにして、初期化されていない(しかし既に割り当てられている)オブジェクトを参照することは明確に定義されているという結論を下します。

間違いがある場合は、私にコメントでお知らせください。また、この回答を編集してください。

編集: 私はちょうどそのような結論が妥当であると言いたいと思います。オブジェクトの初期化はメモリ内の位置を変更することはできません。既に割り当てられたメモリへの参照を初期化される前に保存するのは悪いですか?

+1

2番目の段落は、問題の要点であり、実際はその答えのソースです。答えは「あなたがすることは大丈夫ですが、参照されたオブジェクトを使用すると壊れます」というものです。また、節の代わりに節のヘッダーで段落を参照することも適切です。セクション番号はかなり変わる傾向があります。セクション名はあまり変わりません。したがって、§3.8.6の代わりに[basic.life/6](これはC++ 17の§6.8.7です)。 – StoryTeller

+0

ありがとうございました。あなたが言ったように:「限定された方法でのみ使用されるかもしれない」とは、オブジェクトを使用する§12.7.1の外は罰金であることを示すようです。そして、それはメモリ管理の点で妥当であり、期待されています。 – Flynsee

関連する問題