3

(私の質問への回答にはコピー コンストラクターが含まれますが、コピーは別のクラスへのメソッド呼び出し内ではなく、関数からの戻り時に行われます。参照されている可能性のある重複を実際に見ましたが、vector によって作成されたコピーから推測しませんでした::ここにある私の関数もコピーを作成したことを push_back します。

自動オブジェクトの構築/破壊を理解しようとしています。疑わしいと思われるコードに出くわしたので、それを理解するために独自のバージョンを作成しました。つまり、元のコードには、関数に対してローカルなオブジェクト (自動オブジェクト) を返す関数が含まれていました。それは私には安全ではないように見えたので、それを調べるためにこのプログラムを書きました:

#include <stdio.h>

class Phantom
{
private:
    static int counter;
    int id;

public:
    Phantom()
    {
        ++counter;
        id = counter;
        printf("Phantom %d constructed.\n", id);
    };

    virtual ~Phantom()
    {
        printf("Phantom %d destructed.\n", id);
    };

    void speak()
    {
        printf("Phantom %d speaks.\n", id);
    };
};

int Phantom::counter = 0;

Phantom getPhantom()
{
    Phantom autoPhantom;

    return autoPhantom; // THIS CAN'T BE SAFE
}

int main()
{
    Phantom phantom;

    phantom = getPhantom();

    phantom.speak();

    return 0;
}

私はこの出力を得ます:

ファントム1号建造。
ファントム2号建造。
ファントム 2 が破壊されました。
ファントム 2 が破壊されました。
ファントム 2 がしゃべります。

私を混乱させるのは、出力の 4 行目です。

ファントム 1 はmainを入力すると自動的に構築されます。

ファントム 2 は、getPhantom入力すると自動的に構築されます。

Phantom 2 は終了時に自動的に破棄されますgetPhantom(これが、Phantom 2 からの復帰getPhantomが安全ではないと私が信じている理由です)。

しかし、その後、私は混乱しています。デバッガーによると、出力の 4 行目が表示される前getPhantomに戻ってきました。のデストラクタが 2 回目に呼び出されると、コール スタックは次のようになります。Phantom

主要
〜ファントム

管理された言語では、次の行がどのように表示されるかを確認できました。

phantom = getPhantom();

Phantom 1 は破壊されますが、Phantom 2 には影響しません。これは C++ であり、Java ではありません。

Phantom 2 のデストラクタへの 2 回目の呼び出しの原因は何ですか?

4

6 に答える 6

3

自動ストレージでオブジェクトを返すのは安全ではないというあなたの懸念についてコメントします。

Phantom getPhantom()
{
    Phantom autoPhantom;

    return autoPhantom; // THIS CAN'T BE SAFE
}

それが安全でないなら、C++ は役に立たないでしょうね。私が話していることを確認するには、タイプを次のように置き換えてintください。

int getPhantom()
{
    int autoPhantom = 0;

    return autoPhantom; // How does this look to you now?
}

明確にするために: 値 (つまり、オブジェクトのコピー) を返すため、完全に安全です。

安全でないのは、そのようなオブジェクトへのポインターまたは参照を返すことです。

int* getInt()
{
   int a = 0;
   return &a;
}
于 2016-07-20T12:51:32.877 に答える
2

そのような単純なコードが、一度も構築されていないオブジェクトを破棄するか、何かを 2 回破棄するかを疑問視する代わりに、オブジェクトが構築され、各オブジェクトが 1 回だけ破棄される可能性がはるかに高いと考えてください。ただし、構築と破棄を追跡していません。正確に。

ここで、C++ でオブジェクトを構築する他の方法について考え、任意の時点でコピー コンストラクターを使用するとどうなるかを考えてみましょう。次に、関数からローカル オブジェクトを返す方法と、コピー コンストラクターが使用されるかどうかを検討します。

テスト コードを改善したい場合はthis、デストラクタ内のポインタの値を出力すると、各オブジェクトに ID を与える試みに問題があることがわかります。ID (つまり、メモリ内のアドレス) が異なる複数のオブジェクトがありますが、「ID」は同じです。

于 2016-07-20T12:43:59.250 に答える