C++ STL vector reserve

3

我已经使用以下代码对STL向量进行了测试:

struct structA{
   char charArray[256];
}

structA a;
..assign 256 characters to a.charArray

vector<structA> v1;
v1.reserve(1000);

for(int i=0; i<1000; i++){
   v1.push_back(a);
}

我发现每16个push_back操作,v1.push_back就会出现一个峰值。我怀疑是因为重新分配了内存。但我已经使用了reserve,为什么还会这样呢?我试过使用vectorv1(1000)来声明向量,但结果相同。
顺便说一下,如果我将char增加到512,只需要8个push_back,8 * 512大约需要4k内存。这个问题是否与内存分页有关?
谢谢。

2
也许我们应该去查看或测量,而不是怀疑呢? :) - GManNickG
2
那是如何“实现”的? - Arun
你能详细描述一下问题吗?我不明白发生了什么? - Narek
当你说“...v1.push_back有一个峰值”时,这意味着什么?就目前而言,它没有任何意义。请改进一下。同时,我投票关闭。 - sbi
2个回答

2
运行这个简单的测试,看看是否有任何你不想要或不期望的分配或释放。
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <algorithm>

template <class T> class my_allocator;

// specialize for void:
template <> class my_allocator<void> {
public:
    typedef void*       pointer;
    typedef const void* const_pointer;
    // reference to void members are impossible.
    typedef void value_type;
    template <class U> struct rebind { typedef my_allocator<U>    other; };
};

template <typename T> class my_allocator : public std::allocator<T> {
public:
    typedef size_t    size_type;
    typedef ptrdiff_t difference_type;
    typedef T*        pointer;
    typedef const T*  const_pointer;
    typedef T&        reference;
    typedef const T&  const_reference;
    typedef T         value_type;

    template <class U> 
    struct rebind { 
        typedef my_allocator<U> other; 
    };

    my_allocator() throw() 
    {
    }

    my_allocator(const my_allocator& to_copy) throw() 
    { 
    }

    template <class U> 
    my_allocator(const my_allocator<U>& to_copy) throw()
    {
    }

    ~my_allocator() throw()
    {
    }

    pointer address(reference x) const
    {
        return std::allocator<T>::address(x);
    }

    const_pointer address(const_reference x) const
    {
        return std::allocator<T>::address(x);
    }

    pointer allocate(size_type s1, typename std::allocator<void>::const_pointer hint = 0)
    {
        size_t block_size = s1 * sizeof (T);
        std::cout << "allocated, bytes: " <<  block_size << "\n";
        return std::allocator<T>::allocate(s1, hint);
    }

    void deallocate(pointer p, size_type n)
    {
        size_t block_size = n * sizeof (T);
        std::cout << "deallocated, bytes: " <<  block_size << "\n";
        std::allocator<T>::deallocate(p, n);
    }

    size_type max_size() const throw()
    {
        return std::allocator<T>::max_size();
    }

    void construct(pointer p, const T& val)
    {
        std::allocator<T>::construct(p, val);
    }

    void destroy(pointer p)
    {
        std::allocator<T>::destroy (p);
    }
};


struct structA{
    char charArray[256];
};

int main()
{
    structA a;

    std::cout << "Test 1, with reserve\n";
    {
        std::vector<structA, my_allocator<structA> > v1;
        v1.reserve(1000);
        for(int i=0; i<1000; i++){
            v1.push_back(a);
        }
    }
    std::cout << "Test 1, done\n";

    std::cout << "Test 2, without reserve\n";
    {
        std::vector<structA, my_allocator<structA> > v1;
        for(int i=0; i<1000; i++){
            v1.push_back(a);
        }
    }
    std::cout << "Test 2, done\n";

    return 0;
}

谢谢回复。我会对此进行测试。顺便说一下,如果我将字符增加到512个,只需要8个push_back,8 * 512大约需要4k内存。这是否与内存分页有关? - Steveng
@Steveng:是的,那可能就是原因。内存在你试图访问它之前可能不会映射到你的进程内存空间。 - sharptooth

1
你最好启动调试器并“步入”reserve函数,看看那里发生了什么 - 也许你的STL实现在reserve()上什么都没做。步入push_back()也不会有坏处 - 这样你就可以确切地知道正在发生什么。

reserve()函数确实起到了作用。如果我注释掉reserve,我可以看到在2、4、8、16序列中所花费的时间增加了。 - Steveng

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接