Неэффективно ли использовать std :: vector, когда он содержит только два элемента? - PullRequest
0 голосов
/ 03 апреля 2012

Я создаю класс C ++ A, который должен содержать несколько указателей на другие объекты B.

Чтобы сделать класс как можно более общим, я использую std::vector<B*> внутри этого класса.Таким образом, в A может содержаться любое количество различных B (нет ограничений на их количество).

Теперь это может быть немного излишним, потому что большую часть времени я буду использовать объекты типа A, которые содержат только 2 или 4 B* в векторе.

Поскольку будет много итеративных вычислений с использованием объектов класса A, мне было интересно, много ли накладных расходов связано с использованием вектора B, когданужно только два B.

Должен ли я перегружать класс, чтобы использовать другой контейнер, когда присутствует менее 3 B?

, чтобы прояснить ситуацию: A - это многополюсники, а B - магнитные катушки, которые составляют мультиполи

Ответы [ 4 ]

12 голосов
/ 03 апреля 2012

Преждевременная оптимизация.Получите это работает первым.Если вы профилируете свое приложение и видите, что вам нужна более высокая эффективность (в памяти или производительности), , затем вы можете изменить его.В противном случае это потенциальная трата времени.

2 голосов
/ 03 апреля 2012

Я бы использовал вектор на данный момент, , но , введите для него имя, а не пишите std::vector прямо там, где он используется:

typedef std::vector vec_type;

class A {
    vec_type<B*> whatever;
};

Затем, когда / если это становится проблемой, вы можете изменить это имя typedef для ссылки на вектороподобный класс, который оптимизирован для небольшого числа содержащихся объектов (например, выполняет что-то вроде оптимизации с небольшими строками, которая является обычной много реализаций std::string).

Другая возможность (хотя мне это тоже не нравится) - продолжать использовать имя «вектор» напрямую, но использовать объявление using, чтобы указать, что vector использовать:

class A {
    using std::vector;

    vector<B*> whatever;
};

В этом случае, когда / если необходимо, вы помещаете замену vector в пространство имен и изменяете объявление using, указывая вместо этого:

class A {
    using my_optimized_version::vector;

    // the rest of the code remains unchanged:
    vector<B*> whatever;
};

Что касается реализации оптимизированного класса, типичный способ выглядит примерно так:

template <class T>
class pseudo_vector { 
    T small_data[5];
    T *data;
    size_t size;
    size_t allocated;
public:
// ...
};

Затем, если у вас есть 5 или меньше предметов для хранения, вы помещаете их в small_data. Когда / если ваш вектор содержит больше элементов, чем этот фиксированный предел, вы выделяете пространство в куче и используете data, чтобы указать на него.

В зависимости от того, что вы пытаетесь оптимизировать, вы можете использовать абстрактный базовый класс с двумя потомками, один для маленьких векторов, а другой для больших векторов, с классом, похожим на pimpl, чтобы обернуть их и заставить один действовать как то, что вы можете использовать напрямую.

Еще одна возможность, которая может быть полезна в некоторых ситуациях, - это продолжать использовать std::vector, но предоставить собственный объект Allocator для использования при получении пространства хранения. Поиск в Google для «распределителя небольших объектов» должен привести к появлению нескольких кандидатов, которые уже были написаны. В зависимости от ситуации вы можете использовать один из них напрямую или использовать его как источник вдохновения для написания своего собственного.

2 голосов
/ 03 апреля 2012

Если вам нужен массив B*, который никогда не изменит своего размера, вам не понадобятся возможности динамического сжатия и роста std::vector.

Так что, вероятно, не из соображений эффективности, а из соображений интуиции, вы можете рассмотреть возможность использования массива фиксированной длины:

struct A {
  enum { ndims = 2 };
  B* b[ndims];
};

или std::array (если имеется):

struct A {
  std::array<B*, 2> b;
};

см. Также этот ответ по этой теме.

1 голос
/ 03 апреля 2012

Векторы довольно скудны, поскольку накладные расходы идут. Я уверен, что кто-то здесь может дать более подробную информацию о том, что это на самом деле означает. Но если у вас есть проблемы с производительностью, они не будут исходить от вектора.

Кроме того, я бы определенно избегал тактики использования разных контейнеров в зависимости от количества предметов. Это просто умолять о катастрофе и ничего не даст вам взамен.

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