Накладные расходы на std :: vector размера 1 по сравнению с простым типом - PullRequest
0 голосов
/ 24 марта 2020

У меня есть несколько классов, которые захватывают определенные функции и имеют переменную-член простого типа, например,

float m_a;

Для всех этих классов мне нужна дополнительная версия, где этот член является вложенным вектором такой простой тип, например

std::vector<std::vector<float>> m_a;

Размер векторов не известен во время компиляции, но постоянен в течение времени жизни объекта. Остальные функциональные возможности остаются прежними, только каждый доступ к m_a в первом случае заменяется соответствующим вложенным для -l oop во втором случае.

Очевидно, что второй случай содержит первый случай как особый случай с использованием векторов размера 1 (только m_a [0] [0]).

Это избавило бы меня от написания нескольких новых классов с почти идентичным поведением. Однако объекты этих классов используются (создаются и используются) от тысяч до миллионов раз. Таким образом, вопрос в том, насколько критичны затраты памяти и доступа, создаваемые этим?

Редактировать: я пытался протестировать его с помощью следующей упрощенной программы.

#include <vector>
#include <iostream>
class A{
    public:
    A(float a) : m_a(a) {}; 
    float m_a;
};
class B{
    public:
    B(float b) : m_b({b}) {};
    std::vector<float> m_b;
};
int main(int argc, char** argv){
    unsigned numOfRuns = 10;              // to average out random fluctuations
    for(int r = 0; r < numOfRuns; r++){
        unsigned n = atoi(argv[1]);

        std::vector<A> a;   // simple type
        a.reserve(n);
        clock_t ta1 = clock();
        for(int i=0; i<n; i++){
            a.emplace_back( A(i) );  // create
        }
        clock_t ta2 = clock();

        std::vector<B> b;  // 1-element array
        b.reserve(n);
        clock_t tb1 = clock();
        for(int i=0; i<n; i++){
            b.emplace_back( B(i) );    // create
        }
        clock_t tb2 = clock();

        clock_t ta3 = clock();
        for(int i=0; i<n; i++){
            a[i].m_a;            // access
        }
        clock_t ta4 = clock();

        clock_t tb3 = clock();
        for(int i=0; i<n; i++){
            b[i].m_b[0];        // access
        }
        clock_t tb4 = clock();

        std::cout << n << "\t" << ((tb2-tb1)/(float)(ta2-ta1)) << "\t" << ((tb4-tb3)/(float)(ta4-ta3)) << std::endl;
    }
    return 0;
}

В соответствии с этим создание занимает в 13 раз больше, а доступ - в 1,8 раза. Я также кратко проверил потребление памяти, которое было почти в 10 раз больше для n = 10000000.

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

...