首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >加速C++练习11-6

加速C++练习11-6
EN

Stack Overflow用户
提问于 2013-09-24 14:18:52
回答 4查看 1.1K关注 0票数 5

卡在第11节拍的擦除功能上。我已经销毁了对象,但是我不知道如何使用分配程序库中的去分配来返回空间。

请保释我出去。PS :这不是作业,但我在家练习。

下面是加速C++的代码,然后是修改后的擦除函数。谢谢‘

代码语言:javascript
运行
复制
template <class T> class Vec
{
public:
    typedef T* iterator;
    typedef const T* const_iterator;
    typedef size_t size_type;
    typedef T value_type;
    typedef T& reference;
    typedef const T& const_reference;

    Vec() { create(); }
    explicit Vec(size_type n, const T& t = T()) { create(n, t); }
    Vec(const Vec& v) { create(v.begin(), v.end()); }
    Vec& operator=(const Vec&);
    ~Vec() { uncreate(); }

    T& operator[](size_type i) { return data[i]; }
    const T& operator[](size_type i ) const { return data[i]; }

    void push_back(const T& t)
    {
        if (avail == limit)
        {
            grow();
        }

        unchecked_append(t);
    }

    iterator erase(iterator);
    iterator erase( iterator, iterator );
    void clear();

    size_type size() const { return avail - data; }

    iterator begin() { return data; }
    const iterator begin() const { return data; }

    iterator end() { return avail; }
    const iterator end() const { return avail; }

private:
    iterator data;
    iterator avail;
    iterator limit;

    std::allocator<T> alloc;

    void create();
    void create(size_type, const T&);
    void create(const_iterator, const_iterator);

    void uncreate();

    void grow();
    void unchecked_append(const T&);
};

我的代码

代码语言:javascript
运行
复制
 template <class T> typename Vec<T>::iterator Vec<T>::erase(iterator  first, iterator second )
{
    if( second < first )
    {
        throw std::out_of_range("Iterator out of bounds.");
    }
    if( first < data || second >= avail )
    {
        throw std::out_of_range("Iterator out of bounds.");
    }
    iterator last = avail -1 ;
    iterator i = first ;
    iterator j = second ;  
    while( j <= last )
    {
        *i++ = *j++ ;

    }
    // destroy each initilsed space 
    iterator new_avail =  avail -  first + second ;

    std::cout << " end " << end() << std::endl;

    while( avail != new_avail )
    {
        alloc.destroy(--avail ) ;
    }


    // dellocate  space how to do  that ?
    alloc.deallocate( avail -1,  );  // not sure  what to do  here 
    return first ;

}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-09-24 15:43:47

无法释放已分配内存的一部分。那

alloc.deallocate(效-1,);

是不好的。

编辑

您不应该尝试在擦除中对分配进行管理。你有一个选择是重新分配它,这将使擦除更加昂贵。第二种功能可以做到:

代码语言:javascript
运行
复制
iterator shrink(iterator first, iterator last) {

    size_type capacity = (limit - data) - (last - first);

    iterator new_data = alloc.allocate(capacity);
    iterator new_avail = new_data;
    iterator source = data;
    while(source < first)
        // C++11
        alloc.construct(new_avail++, std::move(*source++));
    source = last;
    iterator result = new_avail;
    while(source < avail)
        // C++11
        alloc.construct(new_avail++, std::move(*source++));
    while(data < avail)
        alloc.destroy(--avail);
    data  = new_data;
    avail = new_avail;
    limit = new_data + capacity;

    return result;
}

更好的选择是这种标准的方式。添加一个额外的构造函数,交换和shrink_to_fit:

代码语言:javascript
运行
复制
Vec(const_iterator first, const_iterator last) {
    create(first, last);
}

void swap(Vec& other) {
    std::swap(data, other.data);
    ...
}

bool shrink_to_fit() {
    try
    {
        Vec(begin(), end()).swap(*this);
        return true;
    }
    catch(...) {}
    return false;
}

现在,您可以对向量应用多个操作,并最终缩小内存消耗。

代码语言:javascript
运行
复制
 v.erase(a, b);
 v.erase(c, d);
...
v.shrink_to_fit();
票数 4
EN

Stack Overflow用户

发布于 2013-09-24 14:30:06

我想,其中一个解决方案是创建一个大小如下的新向量:

代码语言:javascript
运行
复制
new_size = old_size - number_of_elements_to_delete

然后将对象从开始复制到第一个擦除对象,从最后一个擦除对象复制到末尾,然后释放旧的向量。

这不是最好的解决办法,而是我想的最简单的办法。

票数 2
EN

Stack Overflow用户

发布于 2013-09-30 10:10:57

下面是std::allocator::deallocate必须说的话:

void deallocate( pointer p, size_type n ); 分配指针p引用的存储,该存储必须是以前调用allocate()获得的指针。参数n必须等于调用最初生成pallocate()的第二个参数。

也就是说,您不能释放您所分配的存储的一部分,而只能释放整个块。

解决方案是不返回通过调用erase而空闲的存储。只需相应地更新您的成员迭代器,以便在后续调用create时保持此存储的可维护性。这也是标准容器vector所做的。

如果您确实希望返回多余的存储,请分配一个较小的临时块,复制驻留在容器中的元素,释放旧的存储和更新迭代器。

这里要记住的是例外安全。一旦分配了临时缓冲区,就需要确保不会泄漏它,以防在复制元素时出现异常。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18984165

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档