0

次のように std::forward_list を利用するクラスがあります。

void Foo::AddBar(Bar* _bar)
{
  Bars.push_front(_bar);
}

void Foo::DeleteBar(Bar* _bar)
{
  for (forward_list::iterator index = Bars.begin(); index != Bars.end(); ++index)
  {
    if (_bar == *index)
    {
      delete _bar;
      forward_list.remove(_bar);
    }
  }
}

スタックに割り当てられた変数を渡すと、デバッグ/リリースで実行時エラーが発生し、本番環境ではヒープが「マングル」されます。

Bar bar;
foo.AddBar(&bar);
foo.DeleteBar(&bar); // Memory corruption on "delete _bar"

Foo::AddBar がスタックに割り当てられたデータを受け入れないようにするにはどうすればよいですか? これを設計するより良い方法はありますか?


2013 年 6 月 21 日を編集

for ループ内にdelete _bar;andを含めると、反復子がインクリメントするときに実行時エラーが発生します。forward_list.remove(_bar);

私は所有権の管理を完全に Foo に保持し、次のようなテンプレートを使用することにしました。

template<class T> T* AddBar()
{
    Bar* object = new T();
    Bars.push_front(object);
    return object;
}
// Usage looks like...
Process* pid = foo.AddBar<MyBar>(); // adding a subclass of Bar

私はポインターを PID として使用しています - ルックアップの目的で。最初にキャストせずintにユーザーが ing するのを防ぐために、いつでも戻ることができました。deleteああ、私ができる議論のためにAddBar(void* arguments)

4

2 に答える 2

2

簡単に言えば、できません。ポインターはポインターです。そもそもそれらを避けるべきです。それらを使用することを選択した場合は、ドキュメントのポリシーを作成し、コードを適切にレビューしてください。

あなたの例では、所有権の譲渡が発生します(または、少なくとも設計の一部の途中で悪臭を放ちます)、それを文書化する必要があります。この関数は、特定の方法で作成されたオブジェクトのみで呼び出す必要があります。&bar は、これに違反しているとレビューに表示される必要があります。

于 2013-06-21T18:59:46.887 に答える
1

インターフェイスと実装を使用するように変更しますunique_ptr

ユーザーはスタック ポインタを でラップできますがunique_ptr、これが発生していることは少なくとも明らかです。

struct Foo {
  typedef std::vector< std::unique_ptr<Bar> > bar_storage;
  bar_storage bars;
  Bar* AddBar( std::unique_ptr<Bar> );
  void DeleteBar( Bar* bar );
};
void Foo::AddBar(std::unique_ptr<Bar> bar)
{
  Bars.push_back(std::move(bar));
}

void Foo::DeleteBar(Bar* bar)
{
  for (bar_storage::iterator index = Bars.begin(); index != Bars.end(); ++index)
  {
    if (bar == *index)
    {
      Bars.erase(index);
    }
  }
}

私が行ったことは、未定義の動作を呼び出し元のサイトにプッシュすることです。特に:

Bar bar;
foo.AddBar(&bar); // does not compile

代わりに、呼び出し元は次のことを強制されます。

foo.AddBar(std::unique_ptr<Bar>(&bar)); // user just did something really vulgar!
foo.DeleteBar(&bar); // Memory corruption on "delete _bar"

特に、 yourは のfoo所有権を表すため、へBarの追加は、. そのような唯一の所有権を、創造にさかのぼる として表します。あなたが削除する権利を持っているものはであり、あなたが削除する権利を持っていないものはです。BarFooBarstd::unique_ptr<Bar>unique_ptrBar*

于 2013-06-21T20:49:46.153 に答える