2

如何在调用 std::unique 后删除向量中的指针?

例如:

struct Foo
{
    Foo(int bar) : mBar(bar) {}
    ~Foo() { std::cout << "~dtor\n"; }

    int mBar;
};

bool SortFunc(Foo * right, Foo * left) { return right->mBar < left->mBar; }

// Should I 'delete left;' in case of equality?
bool CompareFunc(Foo * right, Foo * left)
{
    return right->mBar == left->mBar;
}

// NOTE: In my code, vector is initialized in another class which I cannot modify.
void InitializeList(std::vector<Foo *> & fooList)
{
    Foo * firstFoo = new Foo(1);
    Foo * secondFoo = new Foo(2);
    // This pointer will not be in vector anymore after std::unique is called!
    Foo * thirdFoo = new Foo(1);
    Foo * forthFoo = new Foo(4);

    fooList.push_back(firstFoo);
    fooList.push_back(secondFoo);
    fooList.push_back(thirdFoo);
    fooList.push_back(forthFoo);
}

int main()
{
    { // Block exists to see if Foo::dtor is called.
    std::vector<Foo *> fooList;
    InitializeList(fooList);

    std::sort(fooList.begin(), fooList.end(), SortFunc);

    std::vector<Foo *>::iterator itrResult = fooList.end();
    // Pointer to thirdFoo is dangling after std::unique is called.
    itrResult = std::unique(fooList.begin(), fooList.end(), CompareFunc);
    fooList.erase(itrResult, fooList.end());

    // ... Other operations and clean up code.
    }
    return 0;
}
4

2 回答 2

5

InitializeList您可以通过立即将其结果包装在智能指针中来将自己与实施不佳的情况隔离开来:

std::vector<std::unique_ptr<Foo>> foos;
{
  std::vector<Foo *> foo_ptrs;
  InitializeList(foo_ptrs);
  foos.assign(foo_ptrs.begin(), foo_ptrs.end());
}

现在您可以打电话std::uniquefoos知道没有任何东西会泄漏。如果您经常这样做,则包装函数可能是一个好主意:

std::vector<std::unique_ptr<Foo>> get_foos() {
  std::vector<Foo *> foo_ptrs;
  InitializeList(foo_ptrs);
  return {foo_ptrs.begin(), foo_ptrs.end()};
}
于 2013-02-04T01:08:14.767 回答
0

正如 juanchopanza 提到的,您需要delete显式调用重复元素。

泄漏在这里:

   fooList.erase(itrResult, fooList.end());

erase简单地删除两个迭代器之间的指针。你必须先打电话delete给他们。

于 2014-05-05T06:55:51.813 回答