4

誰かが呼び出しtest(2)後にオブジェクトが破壊される理由を知ることができますか?test_method()

#include<iostream>
#include<string>

using namespace std;

class test
{
    int n;

    public:
    test(int n) : n(n)
    {
        cout << "test: " << n << endl;
    }

    ~test()
    {
        cout << "~test: " << n << endl;
    }

    test & test_method()
    {
        cout << "test_method: " << n << endl;
        return *this;
    }
};

int main(int argc, const char *argv[])
{
    cout << "main start" << endl;
    const test &test1 = test(1);
    const test &test2 = test(2).test_method();
    cout << "main end" << endl;
}

出力は次のとおりです。

main start
test: 1
test: 2
test_method: 2

~test: 2
main end
~test: 1
4

2 に答える 2

6

test(2).test_method()にバインドされている参照を返します。参照test2するオブジェクトは一時オブジェクトであるため、完全な式の最後で破棄されます。それは驚くべきことではありません。

本当の驚きは、一時に直接test1バインドされているため、有効な参照のままであり、一時を参照にバインドすると、一時の有効期間が参照変数の有効期間まで延長されることです。

test(2)この場合、一時オブジェクトは何にもバインドされていないことに注意する必要があります。これは、いくつかのメンバー関数を呼び出すために使用され、その後、そのジョブが実行されます。それはメンバー機能を「ベビーシッター」しません。言い換えれば、ライフタイム延長はすべての可能な将来の参照を通して推移的ではありません。


これは、「任意の寿命延長」を実際に行うことが不可能である理由の簡単な思考実験です。

extern T & get_ref(T &);

{
    T const & x = get_ref(T());

    // stuff

    // Is x still valid?
}

x最初の行を超えて有効なままであるかどうかはわかりません。get_ref何でもできます。として実装されている場合T & get_ref(T & x) { return x; }、魔法を期待するかもしれませんが、これも可能です。

namespace { T global; }
T & get_ref(T & unused) { return global; }

元の翻訳単位内で、何かを拡張する必要があるかどうかを判断することは不可能です。したがって、現在の標準の方法は、参照宣言式を見るときに行われる、完全に些細なローカルの決定であり、問​​題の一時オブジェクトの存続期間はどうあるべきかということです。

于 2012-05-31T09:33:09.153 に答える
0

C++標準ではこの動作が必要なためです。オブジェクトを永続化する場合は、オブジェクトに名前を付けます。名前がある限り存続します。

編集:あなたの例test1は、最初のオブジェクトに付けた名前ですが、2番目のオブジェクトは名前をまったく取得していないため、式の評価よりも長持ちしません。

于 2012-05-31T09:33:45.053 に答える