Как получить доступ к внутреннему смежному буферу std :: vector и можно ли использовать его с memcpy и т. Д.? - PullRequest
4 голосов
/ 31 августа 2011

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

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

Ответы [ 7 ]

14 голосов
/ 31 августа 2011

На практике практически все компиляторы реализуют vector как массив под капотом.Вы можете получить указатель на этот массив, выполнив &somevector[0].Если содержимое вектора относится к типам POD ("plain-old-data"), выполнение memcpy должно быть безопасным - однако, если это классы C ++ со сложной логикой инициализации, вам будет безопаснее использовать std::. копия 1006 *

10 голосов
/ 31 августа 2011

Просто выполните

&vec[0];

// or Goz's suggestion:
&vec.front();

// or
&*vec.begin();
// but I don't know why you'd want to do that

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

Помните , что если вы добавите или удалитеэлементы из вектора или [потенциально] изменяют вектор любым способом (например, вызывая reserve), этот указатель может стать недействительным и указать на освобожденную область памяти.

6 голосов
/ 31 августа 2011

Вы можете просто сделать:

  &vect[0]

Память гарантированно смежна, поэтому с ней безопасно работать с функциями библиотеки C, такими как memcpy.Однако вы не должны сохранять указатели на смежные данные, потому что векторные размеры могут перераспределять и копировать память в другое место.IE будет плохо:

  std::vector<char> charVect;
  // insert a bunch of stuff into charVect
  ...
  char* bufferPtr = &charVect[0];
  charVect.push_back('a'); // potential resize
  // Now bufferPtr may not be valid since the resize may have moved
  // the vectors contents
  bufferPtr[0] = 'f'; // **CRASH**
2 голосов
/ 31 августа 2011

Самый простой способ - использовать &v[0], где v - ваш вектор.Пример:

int write_vector(int fd, const std::vector<char>& v) {
   int rval = write(fd, &v[0], v.size());
   return rval;
}
2 голосов
/ 31 августа 2011
&myvec[0]

Но обратите внимание, что использование memcpy действительно применимо, только если это вектор POD или примитивных типов.Прямое манипулирование памятью с чем-либо еще ведет к неопределенному поведению.

1 голос
/ 31 августа 2011

Да - поскольку стандарт гарантирует непрерывное размещение внутренних данных vector, вы можете получить доступ к указателю на первый элемент вектора с помощью:

std::vector<int> my_vector;
// initialize...

int* arr = &my_vector[0];
0 голосов
/ 26 апреля 2016

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

    vlad:Code ⧴ cat vectortest.cpp
    #include <vector>
    #include <iostream>
    int main()
    {
        using namespace std;
        vector<char> v(2);
        v.reserve(10);
        char c[6]={ 'H', 'e', 'l', 'l', 'o', '\0' };
        cout << "Original size is " << v.size();
        memcpy( v.data(), c, 6);
        cout << ", after memcpy it is " << v.size();
        copy(c, c+6, v.begin());
        cout << ", and after copy it is " << v.size() << endl;
        cout << "Arr: " << c << endl;
        cout << "Vec: ";
        for (auto i = v.begin(); i!=v.end(); ++i) cout << *i;
        cout << endl;
    }
    vlad:Code ⧴ make vectortest
    make: `vectortest' is up to date.
    vlad:Code ⧴ ./vectortest
    Original size is 2, after memcpy it is 2, and after copy it is 2
    Arr: Hello
    Vec: He
    vlad:Code ⧴

Так что, если вы пишете мимоsize(), тогда новые данные не доступны для методов класса.

Вы можете учесть это и убедиться, что размер достаточно (например, vector<char> v(10)), но вы действительно хотите создавать программное обеспечение там, где вы находитесь?борьба со стандартной библиотекой?

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