0

私のプログラムでは、私が持っているポインタのさまざまなstd::vectorsをクリアするための小さな関数を作成しました。

template <class S>
void clearPtrVector(std::vector<S*> &a,int size)
{
    for(size_t i = 0; i < size; i++)
         delete a[i];

    a.clear();
}

このようなデストラクタでこの関数を呼び出すときから、私はここで何か間違ったことをしたに違いありません:

clearPtrVector(neurons,neurons.size());

次の未定義の参照を2回取得します。

undefined reference to `void clearPtrVector<Neuron>(std::vector<Neuron*,std::allocator<Neuron*> >&, int)'

std :: allocatorが何であるかをよく知らないことを認めなければならないので、ここで問題が何であるかを推測することはできません。どんな助けでも本当にありがたいです。前もって感謝します!

-レフテリス

4

6 に答える 6

8

ホットフィックス

代わりに次のように書いてください。

  template <class Vector>
  void clearPtrVector(Vector &a)
  {
    for(size_t i = 0; i < a.size(); i++)
         delete a[i];

    a.clear();
  }

テンプレートを使用する前に、コンパイラがテンプレートを表示できる場所にテンプレートを定義してください。宣言を作成しない場合は安全である必要があります。そうしないと、コンパイルエラーが発生するはずです。何らかの理由で宣言を作成する場合は、必要に応じてどこにでも定義を含めるように注意してください。

再設計

とはいえ、適切な解決策は、設計を再考し、破壊を適切に処理するコンテナを使用することです。これにより、手動で行う必要がなくなり、面倒で、必要に応じて正しく行うことはほとんど不可能になります。例外安全性。std::shared_ptr生のポインターの代わりに、またはstd::auto_ptrそれらを保持できる(値std::vectorを格納できない)コンテナーとともに使用しauto_ptrます。考えられる解決策の1つは、 BoostPointerContainerを使用することです。

于 2009-05-27T07:54:40.437 に答える
3

clearPtrVectorの実装はヘッダーファイルにありますか?別の.cppファイルにある場合、リンカーはそれを検出しないためです。

于 2009-05-27T08:04:46.797 に答える
3

いくつかのこと:

元のコードでは、サイズを渡さないでください。ベクトルから取得するだけです。

template <class S>
void clearPtrVector(std::vector<S*> &a)
{
    for(size_t i = 0; i < a.size(); ++i)
    {
         delete a[i];
    }

    a.clear();
}

次に、ベクトル自体を渡すだけで、それが指す型ではありません。

template <class Vector>
void clearPtrVector(Vector &vec)
{
    for(size_t i = 0; i < vec.size(); ++i)
    {
         delete vec[i];
    }

    vec.clear();
}

第三に、そのエラーは、.cppファイルに配置されているように聞こえます。コードは、最初に関数を呼び出したときに生成されます。つまり、コンパイラは関数の定義を知っている必要があります。関数をヘッダーファイルに移動して、コンパイラがそれを見つけられるようにします。

最後に、これにより適したものを使用することを検討してください。

于 2009-05-27T08:11:00.437 に答える
2

この関数がヘッダーファイル(.h、*。hpp)にあることを確認してください。これは、ヘッダーファイルにプロトタイプを含むソースファイルで関数を定義すると、未定義の参照リンカーエラーが発生するためです。

未定義の参照エラーは、コンパイラが関数の参照を検出したが、リンカがオブジェクトファイル内でその関数の参照を検出できなかったことを意味します。テンプレート関数はヘッダーファイルで定義する必要があるため、コンパイラはその関数を使用する任意のソースファイルにテンプレート関数を配置できます。

于 2009-05-27T08:09:12.203 に答える
0

再設計は、 cleaning-up-an-stl-list-vector-of-pointersの複製ではありませんか

述べる

スマートポインタの1つを使用しない場合は、deleteの代わりにboost :: checked_delete関数を使用して、不完全な型を削除していないことを確認してください。

于 2009-05-27T08:12:04.333 に答える
0

最初の質問https://stackoverflow.com/questions/891913?sort=newestに対する回答で提供したように、1つの回答は次のとおりです。

template <class C> void FreeClear( C & cntr ) {
    for ( typename C::iterator it = cntr.begin(); 
              it != cntr.end(); ++it ) {
        delete * it;
    }
    cntr.clear();
}

これはすべてのコンテナタイプで機能します。サイズパラメータは提供されていませんが、コレクションから取得されていることに注意してください。これは、このような関数を設計する正しい方法であり、サイズを個別の値として指定すると、災害につながる可能性があります。

于 2009-05-27T08:29:37.917 に答える