C ++ STL векторный резерв - PullRequest
       7

C ++ STL векторный резерв

3 голосов
/ 21 октября 2010

Я тестировал на вектор 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. Я подозреваю, что происходит перераспределение памяти. Мне интересно, почему это так, так как я уже использую резерв? Я попытался объявить вектор, используя vectorv1 (1000), он также дает такое же поведение.

Кстати, если я увеличу символ до 512, потребуется всего 8 push_back, 8 * 512 даст около 4К памяти. Будет ли эта проблема связана с подкачкой памяти?

Спасибо.

Ответы [ 2 ]

2 голосов
/ 21 октября 2010

Запустите этот простой тест и посмотрите, есть ли выделения или освобождения, которые вы не хотите или не ожидаете.

#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;
}
1 голос
/ 21 октября 2010

Ваша лучшая ставка - запустить отладчик и «зайти в» резерв и посмотреть, что там происходит - возможно, ваша реализация STL ничего не делает на reserve().Вступление в push_back() также не повредит - так вы точно будете знать, что происходит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...