2012-04-13 15 views
4

したがって、a questionから別のスレッドで尋ねられましたが、私は新しい質問を考えましたが、答えは私には分かりません。変数の定数とその有効期間

これは、一時的なconst参照がある場合、一時的なものの寿命は少なくともconst参照の長さと同じであるというC++ルールがあるようです。しかし、別のオブジェクトのメンバ変数へのローカルconst参照を持っていて、スコープを離れるときはどうでしょうか?それはその変数のデストラクタを呼びますか?だからここ

は、元の質問からプログラムを変更されます。私はこのコードを実行すると

#include <iostream> 
#include <string> 
using namespace std; 

class A { 
public: 
    A(std::string l) { k = l; }; 
    std::string get() const { return k; }; 
    std::string k; 
}; 

class B { 
public: 
    B(A a) : a(a) {} 
    void b() { cout << a.get(); } //Has a member function 
    A a; 
}; 

void f(const A& a) 
{ //Gets a reference to the member function creates a const reference 
    stores it and goes out of scope 
const A& temp = a; 
cout << "Within f(): " << temp.k << "\n"; 
} 

int main() { 
    B b(A("hey")); 

    cout << "Before f(): " << b.a<< "\n"; 

    f(b.a); 

    cout << "After f(): " << b.a.k << "\n"; 

    return 0; 
} 

だから、私は「ちょっと」値の毎回のように取得します。これは、ローカルのconst参照が、渡されたメンバーオブジェクトとの間に人生を通じて結びついていないことを暗示しているようです。それはなぜですか?

+0

'temp 'が範囲外になったときに' b.a'のデストラクタが呼び出されると思いますか?だから、bは破壊されたメンバーを含むでしょうか? – Henrik

+0

あなたは何を期待していますか?私はb.aが変更される理由は見当たりません。 – Cosyn

+0

http://stackoverflow.com/questions/3097593/what-happens-when-c-reference-leaves-its-scope – EdChum

答えて

10

b.aは一時的なものではないため、その有効期間はその後バインドされる参照の影響を受けません。

+0

これは理にかなっていますが、コンパイラは一時的なものではないことをどのように追跡しますか?データがスタック上またはヒープ上にどこに格納されているかを知っていますか?そのメモリ位置に関連付けられた複数の参照があることをどのように知っていますか?私はたくさんの質問をしていますが、私はC++とそのコンパイラには新しいので、私の好奇心を許してください。 – nndhawan

+0

@nndhawan:コンパイルは式 'b.a'を調べます。これは既存のオブジェクトを参照し、_ 1値です。これはコンパイル時に決定されます。実行時にオブジェクトが実際に格納される場所は関係ありません。 –

+0

ここにはいくつかの基本的な混乱があるようです(恐らく標準自体が言葉に乏しいからです)。一時的な存続期間が延長される唯一の時間は、一時的なもの自体が参照の初期化に使用される場合です。どちらの時点で、コンパイラは一時的な参照と参照の両方を見ることができるので、何をすべきかを知っています。別のリファレンスからリファレンスを初期化すると、ソースリファレンスにバインドされた一時的なライフタイムは延長されません。 –

2

あなたが何を求めているのか分かりません。あなたのコードでは、 はbmainに初期化する式のA("hey")です。コピーコンストラクタを使用してb.aB::Bにコピーします。その後、一時的なものはどこにもありません。

さらに一般的には、一時的に参照番号 にバインドされているという事実は、その有効期間を必ずしも変更しません。寿命を延ばすものは です。一時的に参照を初期化するために使用されるという事実は、 の場合、tempの場合fは一時的に初期化されていないため、 一時的に有効です、 を参照してください。そして、この規則には例外があります:あなたは初期化子クラスの のメンバーの参照を初期化するために、一時的に使用 場合、それはそう、寿命はまだ コンストラクタの終わりを超えて拡張しませんです。

class A 
{ 
    std::string const& rString; 
public: 
    A() : rString(std::string("hey")) {} 
    std::string get() const { retur rString; } 
}; 

動作しないでしょう。

+0

私は一般に誰もが何を言っているかを見ています。しかし、私はこの例がうまくいかない理由を知りません。それは反復的に見える、どのようにrStringを初期化するだろうか? – nndhawan

+0

@nndhawan一時的ではありません。あなたのクラスに参照がある場合、この参照はクラスの外部から取得されたものを参照する必要があります。コンストラクタは引数として参照を受け取ります(そして生涯の問題はクライアントの責任です。 、または他の場所(例えば構成データ)を参照しているものに適用されます。しかし実際には、メンバーとしての参照を持つことは非常にまれです。一般的な解決方法は、すべてのメンバーが参照ではなく値になることです。 –

関連する問題