2009-07-01 8 views
2

このコードスニペットは私に頭痛を与えます。個人的に、私は彼らがすっきりポインタと比較さなどの基準を使用したいので、私はこの試みた:私はこのケースでは、あなたはクラスのメンバ参照に一時変数を割り当てる必要があることを読んだC++のカスタム型参照メンバ - それらを初期化

include "SomeClass.h" 

class FooBar 
{ 
    private: 
    SomeClass& member_; 

    public: 
    FooBar() : member_(SomeClass()) { }; 
} 

をIダミーのSomeClass()を作成してください(私はここでそれをやっているのかどうか分かりません。デフォルトのコンストラクタを指定して試してみました)。ただし、VS 2005で、member_を初期化できないと言ってコンパイルされません。

どうすればいいですか? ありがとうございます!

+0

なお、ポインタを使用する実装を使用するように変更しても問題ありません。 – Extrakun

答えて

3

1のように、あなたが参照としてそれをしたい場合、あなたはおそらくあなたのコンストラクタへの参照を渡したい、値としてmember_を宣言参照しない、または必要がありますどちらか初期化された後に別のオブジェクトを指すようにします。

本当にこの動作が必要ですか?

2)一時オブジェクトで参照を初期化するとき、オブジェクトが有効範囲外です。参照が無効です。

あなたのコードは正しくありません。あなたは今、無駄なメンバーがいます。私は2つの選択肢について考えてみることをお勧めします

a)参照の代わりにポインタを使うことを検討してください。

b)はこのような何かにあなたのコンストラクタを変更します。

MyClass(type & a):membmer_(a){...} 
+0

私は、一度初期化された後、他のオブジェクトを「指す」ことができない参照を完全に忘れてしまった。ありがとう – Extrakun

2

コンストラクタで参照を設定したくないのは間違いですか?すなわち

FooBar(SomeClass& sc) : member_(sc) {}; 

ない場合は、あなたが後でそれを設定しようとしているし、私は、「きちんとした」とされていないにも関わらず、ポインタがあなたの最良の選択肢だと思います。

hereを参照してください。

+0

リンクありがとうございました。私は今それを理解する。 – Extrakun

4

tempはconst参照にのみバインドできます。したがって、変更すると

になります。

あなたはおそらくこれを望んでいません。あなただけの参照を変更することはできません)

FooBar(SomeClass& sc) : member_(sc) { }; 
1

このメンバーは、ポインタまたは参照する必要がありますか?あなたのインターフェイスは簡素化されるかもしれませんが、FooBarのコンストラクタにSomeClassのインスタンスを渡すつもりではありません。これは、クラスが使用するインスタンスが与えられたインスタンスと同じであることを保証するので、参照が有用な場所です。

SomeClassFooBarにカプセル化する予定の場合は、次のようにしてください。 FooBarがインスタンス化されるとき

include "SomeClass.h" 

class FooBar 
{ 
    private: 
    SomeClass member_; 

    // ... rest of your implementation ... 
    // default ctor/dtor is sufficient. 
} 

このコードはSomeClassインスタンスをインスタンス化します。コンパイラによって生成されたクラスデストラクタは、member_に割り当てられたスタックメモリを解放します。

+0

Foobarが作成された後、SomeClassで渡すことを期待していたため、一度参照が参照するものを変更することはできません。ありがとう! – Extrakun

2

標準によれば、一時変数に非const参照を格納することはできません。コンストラクタでSomeClass()オブジェクトを作成すると、一時オブジェクトになり、非const参照として格納しようとしています。ところで、私はここで参照が必要とは思わない。 SomeClass member_;

1

簡単な答え:Jesse氏は、値のメンバーまたはポインタを使用することをお勧めしますが、この具体例では参照しないことをお勧めします。

長い答え:C++のメモリモデルは、CのほうがJavaのようなものです。オブジェクトは存在する可能性があります。

  • がスタックにあります。これは、パラメータとローカル変数の場合です。
  • ヒープ上。これは、newで作成されたすべてのオブジェクトの場合です。データセグメント内の
  • 。これらはグローバル変数です。
  • 他のオブジェクトの内部に値のメンバーとして存在します。

これとは対照的に、Javaではプリミティブ型とポインタ(Javaでは参照と呼ばれます)を除き、すべてのオブジェクトはnewで作成され、スタック上に存在します。この単純なメモリモデルは、不要なオブジェクトを自動的に破棄するガベージコレクタを備えているため、Javaで十分です。

標準C++にはガベージコレクタがありません。オブジェクトは、次のような状況に削除されます。

  • 「それはスコープの外に出た」ときスタックベースのオブジェクトが削除され、
  • アプリケーションが終了したときにグローバルオブジェクトが削除され、
  • に含まれるオブジェクト含まれているオブジェクトが削除されたときに他のオブジェクトが削除されますが、deleteを使用して、ヒープ上のオブジェクトを手動で削除する必要があります(
  • )。

この手動メモリ管理ではエラーが発生する可能性が高いため、通常はC++アプリケーションのオブジェクト間で強力な所有権ポリシーを定義します。

ご質問にお答えいただくには、FooBar-オブジェクトが存在する限り、member_にアクセスできるようにしてください。したがってmember_FooBarのオブジェクトのようなものでない場合、オブジェクトが存在するかぎり存在することが保証されている密接に関連したオブジェクトと同様の方法で類似する方法では、おそらく参照を使用したくないでしょう。私はそうmember_

  • ポインタを含むFooBarを考えるならば、あなたの例では

    、私は

    • 値メンバを使用します。
  • 関連する問題