2010-10-21 3 views
3

Я тестировал на СТЛ вектор с кодом ниже:C++ 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), он также дает такое же поведение.

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

Спасибо.

+2

Возможно, вместо того, чтобы подозревать, мы смотрим или измеряем? :) – GManNickG

+2

Как это было «осознано»? – Arun

+0

Не могли бы вы подробно описать проблему? Я не понимаю, что происходит? – Narek

ответ

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; 
} 
+0

Спасибо за ответ. Я бы испытал на нем. Кстати, если я увеличу char до 512, потребовалось всего 8 push_back, 8 * 512 - около 4k памяти. Будет ли проблема связана с пейджингом памяти? – Steveng

+0

@Steveng: Да, это может быть причиной. Память может не отображаться на вашем пространстве памяти процесса, пока вы на самом деле не попытаетесь получить к ней доступ. – sharptooth

1

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

+0

Резерв() сделал работы. Если бы я прокомментировал резерв, я мог видеть увеличение времени в последовательности 2, 4, 8, 16 – Steveng