代码之家  ›  专栏  ›  技术社区  ›  recipriversexclusion

自定义向量STL容器中的clear()有问题

  •  2
  • recipriversexclusion  · 技术社区  · 15 年前

    遵循中的示例 加速C++ ,我创建了一个自定义STL容器,它是 std::vector ,调用 Vec . 一切都很顺利,直到在成功的鼓舞下,我试图添加一个 Vec::clear() 这将清除向量。

    以下是最新的类定义(仅此问题的相关部分):

    template <class T>
    class Vec {
    public:
        Vec() { create(); }
    
        size_type size() const { return avail - data; }
        size_type capacity() const { return limit - data; }
        void clear();
    
        // operators that return iterators
        iterator begin() { return data; }
        const_iterator begin() const { return data; }
        iterator end() { return avail; }
        const_iterator end() const { return avail; }
    
        void push_back( const T& val ) {
            if ( avail == limit ) grow();
            unchecked_append( val );
        }       
    private:
        iterator data;  // points to beginning of data 
        iterator avail; // points to end of initialized data
        iterator limit; // points to end of data
    
        std::allocator<T> alloc;    // object to handle data allocation
    
        void create();
        // functions to support push_back()
        void grow();
        void unchecked_append( const T& );
    };
    
    // Creates an empty vector.
    template <class T> 
    void Vec<T>::create() { data = avail = limit = 0; }
    
    // All the elements of the vector are dropped: their destructors are called, 
    // and then they are removed from the vector container, 
    // leaving the container with a size  of 0. 
    // The capacity remains the same, however.
    template <class T>
    void Vec<T>::clear()
    {
        std::cout << "capacity before clear: " << capacity() << std::endl;
        std::cout << "data = " << data << " limit = " << limit << std::endl;
        if (data) {
            iterator it = avail;
            // destroy objects in reverse order
            while ( it != data ) {
                alloc.destroy(--it);
            }
        }
        data = avail = 0;
        std::cout << "capacity after clear: " << capacity() << std::endl;
        std::cout << "data = " << data << " limit = " << limit << std::endl;
    }
    
    // Controls how the vector should grow if it needs more space.
    template <class T>
    void Vec<T>::grow()
    {
        // Allocate twice as much storage as is currently used.
        // If matrix is empty, allocate one element.
        size_type new_size = std::max( 2*(limit-data), ptrdiff_t(1) );
    
        // Allocate new space and copy existing elements
        iterator new_data = alloc.allocate( new_size );
        iterator new_avail = std::uninitialized_copy( data, avail, new_data );
    
        // Deallocate old space
        uncreate();
    
        // Reset pointers to new values
        data = new_data;
        avail = new_avail;
        limit = data + new_size;
    }
    
    // Create space for one element at the end and put given value there.
    template <class T>
    void Vec<T>::unchecked_append( const T& val )
    {
        alloc.construct( avail, val );
        avail++;
    }
    

    我用

    Vec<int> v;
    
    for ( int i = 0; i < 100; i++ ) {
        v.push_back(i);
    }
    std::cout << "size=" << v.size() << " capacity=" << v.capacity() << std::endl;
    v.clear();
    std::cout << "size=" << v.size() << " capacity=" << v.capacity() << std::endl;
    

    我得到以下输出:

    size=100 capacity=128
    capacity before clear: 128
    data = 0x100100280 limit = 0x100100480
    capacity after clear: 1074004256
    data = 0 limit = 0x100100480
    size=0 capacity=1074004256
    

    clear() limit 指针。当它甚至没有修改它的时候,这怎么可能呢。代码看起来很简单,但我看不到我遗漏了什么。

    谢谢!

    2 回复  |  直到 15 年前
        1
  •  2
  •   GManNickG    15 年前

    你输了(因此泄漏) data 数据 )留下来。

    你应该替换 data = avail = 0; 具有 avail = data; .

        2
  •  1
  •   Andrey    15 年前

    clear() 应执行以下任一操作:

    • 将向量返回到初始状态(设置 limit 要同时为NULL和释放缓冲区内存,请比较 data = avail = limit = 0; data = avail = 0; )
    • 让它空着,但不要缩水(离开 data 按原样,但已设置 avail 数据 avail = data

    这些规则中没有一条得到实施(你有坏版本的第一)这就是为什么你得到不正确的能力。