Как я могу получить адрес буфера, выделенного vector:: reserve()?

У меня есть 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).... возможно, это не гарантируется?

Ответ 1

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

Ответ 4

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

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

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