Как я могу получить адрес буфера, выделенного функцией vector :: reserve ()? - PullRequest
4 голосов
/ 28 июля 2010

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

void setupBuffer(const size_t maxSize) {
  myVector.reserve(maxSize);
}

void addToBuffer(const Value& v) {
  myVector.push_back(v);

  if (myVector.size() == maxSize) {
    // process data...
    myVector.clear();
  }
}

Однако в setupBuffer мне нужно получить указатель наначало данных myVector.Я использую стороннюю библиотеку, где я должен кэшировать этот указатель заранее для использования в вызове, сделанном в разделе «обработка данных ...».

void setupBuffer(const size_t maxSize) {
  myVector.reserve(maxSize);

  cachePtr(&(myVector[0])); // doesn't work, obviously
}

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

Итак, есть ли способ получить указатель на буфер вектора после выделения (Reserve ()) но до того, как у него есть какие-либо элементы?Я бы предположил, что буфер существует (и не будет двигаться, пока я ограничу количество значений push_back'd) .... может быть, это не гарантировано?

Ответы [ 4 ]

4 голосов
/ 28 июля 2010

Векторный буфер не будет перемещен после вызова в резерв, если вы не превысите зарезервированную емкость. Ваша проблема - получить указатель на первый элемент. Очевидный ответ - вставить одну ложную запись в вектор, получить указатель на нее и затем удалить ее.

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

2 голосов
/ 28 июля 2010

Нет. Вам не разрешен доступ к любому элементу в секторе с индексом, превышающим size. Изменение размера - ваш единственный вариант здесь.

Что вы можете сделать, это что-то вроде:

myvec.resize(SOME_LARGE_VALUE);
myLibrary(&myVec[0]);
myvec.resize(GetSizeUsedByLibrary());

При изменении размера элементы в векторе не уничтожаются, кроме тех, которые имеют индекс выше нового размера. Элементы ниже номера, установленного в resize, остаются одни. Пример использования std::basic_string, но в равной степени применим к вектору

0 голосов
/ 28 июля 2010

Вы пробовали front ()? Кроме того, вы можете push_back элемент, получить адрес, как вы сделали, а затем стереть его.

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

0 голосов
/ 28 июля 2010

Вокруг него много хаков. Но я рекомендую вам правильный способ - переопределить распределитель, второй аргумент шаблона:

typedef std::vector<MyItem, MyAllocator> myvector_t;

После этого в MyAllocator обеспечить фиксированное выделение буфера и передать этот экземпляр распределителя в качестве аргумента конструктора вектора

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