2

で SmartPtr クラスを初期化しnew Time(1,0,0)ます。

    //main.cpp 
    int main()
{
    SmartPtr pTime0(new Time(0,0,1));
}

どこにも delete を呼び出していませんnew Time(1,0,0)。すべてが正常に動作し、プログラムは準拠して実行されます。しかし、私は混乱していdelete Time(1,0,0)ます。

ここで作成および削除する一時オブジェクトの概念がわかりません。どこかに書くときはいつでも、私は書かnewなければならないことを知っていdeleteます!誰かがどこ delete Time(1,0,0)で行われるのか説明してもらえますか?

SmartPtr pTime0(new Time(0,0,1)) <--newここでは新しく割り当てられたメモリへのポインタを返し、 ctornewで 2 回目にメモリを割り当てますか??

//SmartPtr.cpp 

SmartPtr::SmartPtr(Pointee * p):_pointee(new Pointee(*p))
{}

SmartPtr::~SmartPtr()
{
    delete _pointee; 
}
4

4 に答える 4

2

SmartPtr私はあなたのクラスの詳細を知りません。

いずれにせよ、次のようなコンストラクタがある場合:

SmartPtr::SmartPtr(Pointee * p):_pointee(new Pointee(*p))
{}

そしてこれはデストラクタです:

SmartPtr::~SmartPtr()
{
    delete _pointee; 
}

次に、このコードで:

SmartPtr pTime0(new Time(0,0,1));

の 1 つのインスタンスをリークしますTime(0,0,1)

実際、(2 s と 1 )newよりも1 つ多くあります。deletenewdelete

ステップ #1:new Time(0,0,1)ヒープ上に新しいオブジェクトを呼び出して作成します。
(newカウント == 1)

ステップ #2: このポインターをSmartPtrコンストラクターに渡します。これにより、以前に作成されたオブジェクトがディープ コピー_pointeeされ、新しいコピーがヒープに割り当てられ、データ メンバーを介してこのコピーが追跡されます。
(newカウント == 2)

ステップ #3:SmartPtrデストラクタが実行されると、データ メンバーがdelete指すインスタンスになりますが、ヒープ上に作成された最初のものを でリークしました。 (カウント == 1;カウント == 2)_pointeeTime(...)new Time(0,0,1)
deletenew

それに対する可能な修正は、このコンストラクターを持つことです:

SmartPtr::SmartPtr(Pointee * p)
    : _pointee(p) // <--- transfer ownerhsip (no deep copies) !
{}

このような場合に潜在的なリークを特定する簡単な方法は、コンソール トレース出力をTimeクラス コンストラクターとデストラクターに配置し、デストラクターのトレース出力がコンストラクターのトレース出力と一致することを確認することです。次に例を示します。

Time::Time(....)
{
    // Do construction work....

    std::cout << "Time constructor\n";
}

Time::~Time(....)
{
    // Do destructor work....

    std::cout << "Time destructor\n";
}

文字列の総数は、"Time constructor"文字列の総数と一致する必要があり"Time destructor"ます。

于 2013-09-25T18:32:55.747 に答える
1

2 つの修正方法:

メソッド A、呼び出し元が割り当て、SmartPtr が所有権を取得します。

SmartPtr::SmartPtr(Pointee * p):_pointee(p)
{
}

メソッド B、呼び出し元がコンテンツを提供し、SmartPtr が割り当てます。

SmartPtr::SmartPtr(Pointee v):_pointee(new Pointee(std::move(v)))
{
}

デストラクタは同じままです。

SmartPtr::~SmartPtr()
{
    delete _pointee; 
}
于 2013-09-25T19:29:29.150 に答える
0

new と入力しないという原則に従って、アプリケーションを作成できます。
これを既存のスマート ポインターと組み合わせると、次のようになります。

#include <memory>    // this is where the smart-pointers live
#include "Time.h"    // or whatever header defines your "Time" class

int main()
{
    // note that make_shared is essentially a forwarding constructor,
    // give it whatever parameters Time's constructor would take
    auto p = std::make_shared<Time>(0,0,1); 
    // use p here
}

そして、これまでに何かが漏れることはありません。

「Never type new」は、低レベルのリソース管理ライブラリを作成する必要がある場合を除いて、すべてのアプリケーション プログラミングに適用する必要があります。

クラスがリソース管理を行う場合は、それが唯一の機能であることに注意してください。

他のすべてのクラスはゼロのルールに従う必要があります

于 2015-08-25T22:36:47.893 に答える
0

この式new Time(0,0,1)は、ヒープ上の永続オブジェクトへの一時ポインターを作成します。一時ポインターは確かに自動的に破棄され (これはノーオペレーションです)、オブジェクトはヒープ上に残りますが、参照されません。漏れが発生しました。

リークを防ぐには、ポインターをどこかに保存し、最終的に削除が呼び出されるようにしてください。

于 2013-09-25T18:27:35.320 に答える