从指针向量中擦除元素并取消分配先前通过new运算符分配的动态内存? [英] Erase elements from a vector of pointers and deallocate the dynamic memory previously allocated via new operator?

查看:66
本文介绍了从指针向量中擦除元素并取消分配先前通过new运算符分配的动态内存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想向您展示这个非常简单的示例,目的是对一些动态分配的字符串进行排序,并清除重复的副本,从而调整向量的大小并释放无用的占用的内存.

I want to show you this very simple example, the purpose is to sort some strings allocated dynamically and clean the duplicates resizing the vector and deallocating useless occupated memory.

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

void print_v (vector<string *>& v)
{
    cout << "----" << endl;
    for (string*& str : v)
        cout << *str << " ";
    cout << endl << "----" << endl;
}

typedef string * string_ptr;

int main() 
{
    vector<string_ptr> v;
    v.push_back(new string("aba"));
    v.push_back(new string("baba"));
    v.push_back(new string("saba"));
    v.push_back(new string("aba"));
    v.push_back(new string("naba"));
    v.push_back(new string("aba"));
    v.push_back(new string("saba"));
    v.push_back(new string("laba"));

    print_v(v);

    sort(v.begin(), v.end(), [](const string_ptr &a, const string_ptr &b){ 
        return a->compare(*b) < 0; 
    });

    auto last = unique(v.begin(), v.end(), [](const string_ptr &a, const string_ptr &b) {
        return a->compare(*b) == 0;
    });

    print_v(v);

    for_each(last, v.end(), [](string_ptr &a){
        delete a;       //if I comment this line everything works "fine"
        a = nullptr;
    });

    v.erase( find(v.begin(), v.end(), nullptr) , v.end() );

    print_v(v);
}

为什么这种东西不起作用?如果我用delete注释行,则一切正常,但我当然有内存泄漏.另一个问题:如果在lambda函数的签名中使用string*(而不是typedef string_ptr),会出现讨厌的编译错误,为什么?

Why this kind of stuff didn't work? If I comment the line with delete everything works fine but I have of course memory leaks. Another question: if in the signature of the lambda functions I use string* (instead of the typedef string_ptr) I get nasty compilation errors, why?

对不起,我的英语不好,我希望问题很清楚.

Sorry for my bad english, I hope the questions are clear enough.

推荐答案

如上所述,std::unique函数基本上使那些放置在返回的迭代器僵尸元素右侧的项成为可能.可以访问它们,但是它们没有用.这就是将delete应用于这些项目时无法正常工作的原因.

As stated, the std::unique function basically makes those items that are placed on the right-side of the returned iterator zombie elements. They can be accessed, but they're useless. That's why your delete does not work correctly when you applied it to these items.

如果您的目标是划分唯一项,但同时又保持其有效性,则可能要使用的算法功能为

If your goal is to partition off the unique items, but at the same time keep their validity, the algorithm function you may want to use is std::stable_partition, with a usage of std::set. So in place of std::unique, you can do the following:

#include <algorithm>
#include <set>
//...
std::set<std::string> stringset;
auto last = std::stable_partition(v.begin(), v.end(), [&stringset](const string_ptr& a) 
{
   if ( stringset.count(*a) )  return false;
    stringset.insert(*a); return true;  
});

基本上,我们使用std::set存储最初找到的值.在随后调用lambda函数时,我们通过查询set::count()函数来检查重复项.如果返回1,则该项目已存在于集合中,否则返回0.因此,要将重复的项目放置在分区的右侧,我们需要返回false,而全新的项目则需要返回true(如果是新项目,我们还将其添加到集合中).因此,基本上,我们已经使用std::stable_partition编写了std::unique的无损版本.

Basically, we use the std::set to store values we initially find. On subsequent calls to the lambda function, we check for duplicates by querying the set::count() function. If it returns 1, then the item already exists in the set, 0 otherwise. So to place the duplicate items to the right of the partition, we need to return false, and brand new items, we return true (and also we add the item to the set if it's a new item). So basically, we've written a non-destructive version of std::unique by using std::stable_partition.

因此,这导致不仅将唯一项划分为返回的std::stable_partition迭代器的右侧,而且这些项是完全有效的,并且可以用于您认为合适的任何目的(在您的情况下,您想delete他们.

Thus this results in the unique items not only being partitioned off to the right of the returned iterator of std::stable_partition, those items are perfectly valid and can be used for whatever purpose you see fit (in your case, you wanted to delete them).

请注意,这是可行的,如此实时示例

Note that this works, as shown by this Live Example

此外,您可以使用std::partition,但是此功能不会保留项目的相对顺序.您可能想使用std::partition代替,但是我假设您想保持元素的顺序.

Also, you could use std::partition, but this function does not preserve the relative order of the items. You may want to use std::partition instead, but I am assuming you want to keep the order of the elements.

这篇关于从指针向量中擦除元素并取消分配先前通过new运算符分配的动态内存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆