C ++ вектор с динамическим размером элемента - PullRequest
3 голосов
/ 09 июня 2011

вектор C ++ STL имеет много приличных свойств, но работает только тогда, когда размер каждого элемента известен во время выполнения.

Я хотел бы иметь векторный класс, который имеет динамический размер элемента ввремя выполнения.

Справочная информация: Мои элементы состоят из последовательности целых и двойных чисел;последовательность, которая известна только во время выполнения.Было бы достаточно, чтобы вектор получил размер каждого элемента во время выполнения.

Я знаю о возможных обходных путях, но они, как правило, не отражают основную идею алгоритма, что всегда плоховещь в отношении поддержания.Существуют ли классы, которые обеспечивают такое удобство и работают так эффективно, как можно было бы ожидать?

РЕДАКТИРОВАТЬ:

Дело не в размерах элементов, варьирующихся по всему массиву.Это не имеет ничего общего с этим.Во время выполнения решается, насколько велики элементы в массиве;то есть (очень) слабая форма динамической типизации, в отличие от статической типизации, используемой с шаблонами.

Следовательно, инициализация объекта должна выглядеть следующим образом:

DynamicVector V( lengthofvector, sizeofelement );

Приложениесимплициальные сетки.Объект $ V $ содержит элементы фиксированного размера или «типа», каждый из которых состоит из целых чисел для топологической информации и удваивается для некоторой геометрической информации.Могут даже появиться логические значения, но это пока не имеет значения.

Ответы [ 9 ]

4 голосов
/ 09 июня 2011

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

Как насчет простого хранения ВСЕХэлементы как double?Это существенно упрощает вещи.

В качестве альтернативы вы могли бы рассмотреть boost::variant.

РЕДАКТИРОВАТЬ: Но действительно ли вы можете объяснить, почему вы хотите хранить два разных типа в одной последовательности?Иногда это может указывать на то, что основополагающий проект нуждается в дальнейшей доработке.

1 голос
/ 09 июня 2011

Если это просто последовательность int и double, то вы можете просто использовать:

 std::vector<double> sequence;

, а затем вставьте int и double в него. Тем не менее, этот подход не отслеживает тип предметов. Если тип важен для вас, то, вероятно, вам может помочь следующее:

struct item
{
  union 
  {
     int i;
     double d;
  } data;
  char type; //store 0 for int, 1 for double;
};

std::vector<item> sequence;

Конечно, такой подход стоит по крайней мере один дополнительный байт на элемент для хранения типа элемента. Возможно, вы захотите использовать #pragma pack технику, чтобы выжать дополнительный отступ.

Или, что еще лучше, переработайте ваш код так, чтобы вместо одной последовательности было две последовательности:

std::vector<int>     intSeq;
std::vector<double>  doubleSeq;
1 голос
/ 09 июня 2011

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

0 голосов
/ 13 сентября 2011

Я видел этот вопрос раньше! Существует ли контейнер STL, который хранит массив элементов в непрерывной памяти, где размер элемента указан во время выполнения?

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

typedef Toffset uint; //byte offset;
typedef Ttype   uint; //enum of types
typedef std::pair<Toffset,Ttype> member;
typedef std::unordered_map<std::string, member> memberdefs;

И я разработал (непроверенный) класс для этого Полный код находится в ссылке, но прототипы:

class interleaved_vector {
    const char* buffer;
    size_t count;
    size_t size;
    std::shared_ptr<memberdefs> members;
public: 
    class dynamic_object {
        const char* buffer;
        std::shared_ptr<memberdefs> members;
        friend interleaved_vector;
        dynamic_object(const char* buffer_, std::shared_ptr<memberdefs> members_);
        dynamic_object& operator=(const dynamic_object& b) = delete;
    public:
        dynamic_object(const dynamic_object& b) ;
        template <class T>
        T get(const std::string& member) const;
        template <>
        T* get<T*>(const std::string& member) const;
        void* operator[](const std::string& member) const;
    };
    interleaved_vector(const char* buffer_, size_t count_, size_t size_, const memberdefs& members_);
    dynamic_object get(size_t index) const;
    dynamic_object operator[](size_t index) const;
    size_t size();
};

В качестве предупреждения: оно полагается на какое-то поведение, которое, как мне кажется, не определено и вообще является плохой идеей. Перейти с вектором указателей.

0 голосов
/ 10 июня 2011

Я думаю, что лучший способ продвижения вперед (с точки зрения производительности и обслуживания) - это обходной путь, при котором вы помещаете std :: vector и std :: vector в два класса, которые объединяют общий базовый класс с соответствующим интерфейсом.

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

0 голосов
/ 10 июня 2011

Используйте std :: vector, где item - это обернутый умный указатель. Класс "item" делает указатель похожим на простое значение:

class item {
private:
    boost:unique_ptr<base> p;
public:
    // ...
    public item(item that);

    public int someFunction() {
       // Forwarded
       return p->somefunction();
    }
};

class base {
    virtual ~base();
    // This is needed in order to implement copy of the item class
    virtual base* clone();
};

public item::item(item that) : p(that.p.clone()) {}

class some_real_type() : public base {
   // ....
}
0 голосов
/ 09 июня 2011

Создайте класс, который содержит три вектора: один для целых чисел, один для двойников и один, в котором есть запись для каждого элемента, чтобы указать тип соответствующего элемента и его индекс в соответствующем векторе.

0 голосов
/ 09 июня 2011

Если вы не хотите прибегать к обходным решениям , я думаю, вам следует подумать об абстракции этих "элементов динамического размера".Он должен быть спроектирован с учетом того, что он должен использоваться внутри вектора STL (тогда должны быть гарантированы некоторые реквизиты), так что вы можете наконец написать что-то вроде:

std::vector<DynamicSizedItem> myVector;
0 голосов
/ 09 июня 2011

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

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

Если ваши целые и двойные числа имеют одинаковый размер (например, 64 бита), вы можете использовать объединение для доступа к каждому элементу либо как целое число, либо как двойное.Но вам нужен способ узнать, каким должен быть каждый элемент.

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