ポインターのベクトル テンプレートのクリア関数がコンパイルに失敗し、「未定義の参照」メッセージが表示される

StackOverflow https://stackoverflow.com/questions/914460

  •  06-09-2019
  •  | 
  •  

質問

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

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 が何なのかよく知らないので、ここで何が問題なのか推測できません。ご協力をよろしくお願いいたします。前もって感謝します!

-レフテリス

役に立ちましたか?

解決

ホットフィックス

代わりに次のように記述します。

  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 つは、 ブーストポインタコンテナ

他のヒント

は、ヘッダファイルでのごclearPtrVectorの実装ですか?それは別の.cppファイルにいた場合、リンカはそれを見つけることができませんので。

いくつかのこと:

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

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 ファイルに配置されているようです。コードは、最初に関数を呼び出したときに生成されます。つまり、コンパイラーは関数の定義を知る必要があります。コンパイラが関数を見つけられるように、関数をヘッダー ファイルに移動します。

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

あなたはヘッダファイルにプロトタイプを持つソースファイルに定義された場合は、未定義の参照リンカエラーを得ますので、あなたがヘッダファイル(.H、* .HPP)でこの機能を持っていることを確認してください。

未定義の参照のエラーは、コンパイラは、関数の参照を見つけたが、リンカは、オブジェクトファイルの中でその関数の参照を見つけることができなかったことを意味します。任意のテンプレート関数は、コンパイラは、関数を使用するすべてのソースファイルにそれを置くことができるようになりますので、ヘッダファイルに定義する必要があります。

再設計はの重複ではありませんかポインタの stl リストベクトルのクリーンアップ

述べる

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

私はあなたの最初の質問に私の答えで提供されるように 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();
}

すべてのコンテナタイプのために働きます。サイズパラメータが用意されていませんが、コレクションからobrtainedされることに注意してください - 。これが唯一の災害につながることができ、別の値としてサイズを提供するような関数を設計する正しい方法です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top