2

重複の可能性:
変更可能なメンバーを返すには?

割り当て (および呼び出されたメソッド シグネチャ) で const& を使用すると、被参照オブジェクトの有効期間がメソッドの最後まで延長されることを学びます。

Employee const& getEmp(int a) {
    return Employee(a);
}
Employee const& tmpEmp = m.getEmp(10);  //
... stuff 
//end of scope - tmpEmp valid until here

私は小さなプログラムを書き、それが期待通りに動作することを確認しました。私の質問は、これを行う方法ではありませんか?私の質問は、コンパイラがこれをどのように行うかについてです。例を見るとreturnの直後にデストラクタが呼ばれるので、どうやってデストラクタを呼んだのだろうと思うのですが、tmpEmpはデストラクタを呼んだ後に有効なのですか?

#include <iostream>
using namespace std;

class Employee {
public:
    Employee() : a(0){
        cout << "c-emp" << a << endl;
    }
    Employee(const Employee& newE) {
        a = newE.a;
        cout << "c-c-emp" << a << endl;
    }
    Employee(int a) : a(a) {
        cout << "c-emp" << a << endl;
    }
    ~Employee() {
        cout << "d-emp" << a << endl;
    }
    int a;
};
class Manager {
public:
    Manager() {}
    ~Manager() {}
    Employee const& getEmp(int a) {
        return Employee(a);
    }
};

int main(int argc, char **argv) {
    Manager m;
    Employee const& tmpEmp = m.getEmp(10);
    cout << "tmpEmp " << tmpEmp.a <<endl;
}

output:
c-emp10
d-emp10   - destructor is called and tmpEmp is still valid? how is that?
tmpEmp 10
4

2 に答える 2

3

あなたは間違って学びました。

まず、代入がオブジェクトの存続期間に影響を与えることはありません。副作用のある単なる演算子です。

第 2 に、const 参照を一時オブジェクトで初期化する (代入しない) 場合、一時オブジェクトの有効期間は、参照の有効期間と一致するように延長されます。ただし、例外もあります。(そして、この機能の実用的な用途を見つけたことはありません。)

戻り値として使用される const 参照は例外の 1 つです (実装できないという単純な理由による)。const 参照型の戻り値を一時オブジェクトで初期化しても、一時オブジェクトの寿命は延長されません。

そして最後に、仮に初期化された参照が関数を呼び出す完全な式の後に存在しなくなるため、あなたのケースでは役に立ちません。

于 2012-08-01T15:20:04.457 に答える
3

あなたのコードは間違っています。ローカル オブジェクトへの参照を返していますが、ローカル オブジェクトは、学習した有効期間の延長の対象ではありません。ローカル オブジェクトの有効期間は、戻り値を別の変数に代入する前に終了するため、有効期間を延長する方法はありません。

有効期間の延長は、一時オブジェクト用です。

Employee getEmp(int a) {
    return Employee(a);
}
Employee const& tmpEmp = m.getEmp(10);  //
... stuff 
//end of scope - tmpEmp valid until here

getEmp() は一時オブジェクト (ローカル オブジェクトへの参照ではない) を返すようになり、そのオブジェクトは代入が発生したときにも有効です。そのため、寿命が延びます。

于 2012-08-01T15:17:47.773 に答える