1

さて、すべての定義を含むクラスがあるとしましょう、bla bla bla ...

template <class DT>
class Foo{
private:
    DT* _data;
    //other stuff;
public:
    Foo(DT* data){ _data = data; }
    virtual ~Foo(){ delete _data; }
    //other methods
};

そして、私はメインメソッドに持っています:

int main(){
    int number = 12;

    Foo<anyRandomClass>* noPrimitiveDataObject = new Foo<anyRandomClass>(new anyRandomClass());
    Foo<int>* intObject = new Foo<int>(number);

    delete noPrimitiveDataObject; //Everything goes just fine.
    delete intObject; //It messes up here, I think because primitive data types such as int are allocated in a different way.

    return 0;
}

私の質問は次のとおりです。メイン メソッドの両方の削除ステートメントを正常に機能させるにはどうすればよいでしょうか。

PS: この特定のコードを実際にコンパイル/テストしたわけではありませんが、(インデントも含めて) 広範囲にレビューしたので、間違いを見つけた場合はよろしくお願いします。

4

2 に答える 2

2

リテラルのアドレスを取得し、後でそれを呼び出しdeleteていますが、これは間違っています。で割り当てられていないnewため、で割り当てを解除することはできませんdelete(また、意味がありません)。

代わりに書いていればnew int(12)問題ありませんが、他にも問題があります。

まず、あなたのクラスはThe Rule of Threeに違反しています。両方をコピーintObjectして呼び出すとどうなりますか? 同じポインターを 2 回delete呼び出すことになります。delete

第二に、そもそもなぜこれらのものを動的に割り当てるのですか? 割り当て解除を処理する RAII スタイルのラッパーを作成し、手動で割り当てます。それはどのような問題を解決していますか?

これはあなたのための演習だと思います。それは素晴らしいことです。このコードで解決しようとしている問題を覚えておいてください。

を使用std::vector<T>している場合、次のように使用するつもりはありません。

std::vector<int> *v = new std::vector<int>;

ベクトルを使用する目的全体を無効にします。このポインタ/メモリを手動で管理する必要があります。この問題を解決するために、ベクトル クラス (およびその他の RAII スタイル クラス) が作成されました。

したがって、適切に使用するには、次のようにします。

void foo() 
{
    std::vector<int> v;
    // do stuff with v
    // it allocates its memory dynamically so you don't have to.
    // when we exit the function the destructor is called, the memory 
    // deallocated, and life continues as it should.
}

自動保存期間を有利に使用してください。それが要点です。また、誰がメモリを所有しているかについても明確にしてください。誰が特定のメモリ チャンクを所有しているかがクラス設計から明らかでない場合delete、デストラクタでは安全ではありません。


OK、コードを次のように変更しました。

int number = 12;
// ...
Foo<int>* intObject = new Foo<int>(number);

同じ問題; 自動保存期間で割り当てられた変数のアドレスを取得し、それを呼び出しdeleteています。 これは間違っています。で割り当てたものはすべてnew割り当てを解除しますがdelete、それ以外は何もしません。これまで。それでおしまい。

于 2012-10-24T22:51:25.427 に答える
1

できることを知らなかったようですnew int(12)。たとえば、コードを次のように変更できます。

Foo<int>* intObject = new Foo<int>(new int(12));

new(完全に使用しない方が良いので、これは学習のためだけだと思います)。

また、あなたのコードが間違っていることに気付きました.おそらくあなたは次のことを望んでいました:

Foo(DT* data){ _data = data; }
virtual ~Foo(){ delete _data; }

サイドノート

質問を投稿する前に、少なくとも例をコンパイルしてみてください。

于 2012-10-24T22:50:56.173 に答える