2

次のコードは、を変更するデストラクタを利用していますi。デストラクタが実行されると、リターン時にまだに2格納されることになっています。ithing()-1

#include <stdio.h>

class Destruct {
    int &i;
public:
    Destruct(int &_i) : i(_i) {}
    ~Destruct() {
        i = 2;
    }
};

int thing() {
    int i = -1;
    Destruct d(i);
    return i;
}

int main() {
    printf("i: %d\n", thing());
}
4

2 に答える 2

12
int thing() {
    int i = -1;
    Destruct d(i);
    return i;
}

関数が戻るとオブジェクトdが破棄され、スタックのクリーンアップが開始されます。デストラクタが呼び出されるまでに、戻り値はすでに戻りレジスタにコピーされています。

見たいものは、これを行うことで見ることができます:

int thing() {
    int i = -1;
    {
        Destruct d(i);  //put it inside braces!
    }
    return i;
}

あなたのコメントから:

それがどのように機能するかです。コードの逆アセンブルは、これが事実であることを示しています。その理由が気になります。

iロジックは簡単で、次のように証明できます。リターン レジスタにコピーされる前にデストラクタが呼び出されたdとしiます。結局のところ、両方ともローカル変数ですd。したがって、が破壊された場合、その値がリターンレジスタにコピーされる前にi、同様に破壊する必要がありますが、それは意味がありません。

そして、@Luc Touraille が (コメントで) 尋ねたように、「関数が返されdたらどうしますか? 呼び出し元に渡されるdに破壊されてもよろしいですか?」

于 2012-07-27T11:00:00.643 に答える
3

ステートメント内の i のコピーが作成された後に、デストラクタが実行されるためreturn iです。

in をグローバルにして参照渡しでプログラムを変更すると、i必要なものが表示されます。

#include <stdio.h>

int i = -1;
class Destruct {
    int &i;
public:
    Destruct(int &_i) : i(_i) {}
    ~Destruct() {
        i = 2;
    }
};

int& thing() {
    Destruct d(i);
    return i;
}

int main() {
    printf("i: %d\n", thing());
}
于 2012-07-27T10:59:46.363 に答える