从向量中删除对象内存的最佳方法

Swa*_*nil 2 c++ vector heap-memory

我有vector包含堆上分配的对象.我想从向量中删除一些元素.哪个是从vector中删除元素并删除它的最佳方法.

在以下代码中尝试了一种方法:

class MyObj
{
    bool rem;
public:
    MyObj(bool r) : rem(r) { cout << "MyObj" << endl; }
    ~MyObj() { cout << "~MyObj" << endl; }

    bool shouldRemove() const noexcept { return rem; }
};


int main()
{
    vector<MyObj*> objs;
    objs.push_back(new MyObj(false));
    objs.push_back(new MyObj(true));
    objs.push_back(new MyObj(false));
    objs.push_back(new MyObj(true));

    auto itr =  objs.begin();
    while (itr != objs.end())
    {
        if ((*itr)->shouldRemove())
        {
            delete *itr;
            *itr = nullptr;

            itr = objs.erase(itr);
        }
        else
            ++itr;
    }

    // size will be two
    cout << "objs.size() :" << objs.size() << endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Rem*_*eau 6

你的循环很好,只要删除和delete对象(nullptr分配是不必要的).但是其余的代码容易出现内存泄漏.如果push_back()抛出,你会泄漏刚才的物体new.并且delete在循环结束后,您不是仍然在向量中的对象.

哪个是从vector中删除元素并删除它的最佳方法

最佳选择是在所有不使用原始指针.将实际对象实例直接存储在向量中,让向量在移除它时为您破坏实例,并在向量本身超出范围时对其进行破坏:

int main() {
    std::vector<MyObj> objs;

    objs.emplace_back(false);
    objs.emplace_back(true);
    objs.emplace_back(false);
    objs.emplace_back(true);

    auto itr = objs.begin();
    while (itr != objs.end()) {
        if (itr->shouldRemove())
            itr = objs.erase(itr);
        else
            ++itr;
    }

    /* alternatively:
    objs.erase(
        std::remove_if(objs.begin(), objs.end(),
            [](auto &o){ return o.shouldRemove(); }),   
        objs.end()
    );
    */

    // size will be two
    std::cout << "objs.size() :" << objs.size() << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

否则,如果需要存储指向动态分配对象的指针,至少使用智能指针来管理它们:

int main() {
    std::vector<std::unique_ptr<MyObj>> objs;

    objs.push_back(std::unique_ptr<MyObj>(new MyObj(false)));
    objs.push_back(std::unique_ptr<MyObj>(new MyObj(true)));
    objs.push_back(std::unique_ptr<MyObj>(new MyObj(false)));
    objs.push_back(std::unique_ptr<MyObj>(new MyObj(true)));

    /* alternatively, if you are using C++14 or later
    objs.push_back(std::make_unique<MyObj>(false));
    objs.push_back(std::make_unique_ptr<MyObj>(true));
    objs.push_back(std::make_unique<MyObj>(false));
    objs.push_back(std::make_unique<MyObj>(true));
    */

    auto itr = objs.begin();
    while (itr != objs.end()) {
        if ((*itr)->shouldRemove())
            itr = objs.erase(itr);
        else
            ++itr;
    }

    /* alternatively:
    objs.erase(
        std::remove_if(objs.begin(), objs.end(),
            [](auto &o){ return o->shouldRemove(); }),  
        objs.end()
    );
    */

    // size will be two
    std::cout << "objs.size() :" << objs.size() << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)