c ++ vector Как изменить внутренний указатель - PullRequest
2 голосов
/ 21 октября 2010

Я хотел бы сериализовать вектор. И я не знаю, как изменить указатель вектора .. Для простоты, скажем, у меня есть вектор что-то вроде:

vector<char> v;

И у меня есть этот указатель:

char* c = { 'v', 'e', 'c', 't', 'o', 'r' };

И мне бы хотелось, чтобы внутренний указатель моего вектора v указывал на мой символ * c:

&v[0] -> c 

Как мне отрегулировать вектор так, чтобы он указывал на c? Есть ли способ сделать это?


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

Так, ребята, после отладки вектора я придумал это решение:

vector<char> dump;
memcpy(&myVector, &dump, sizeof(myVector)); // I change contents so it can work
myVector.assign(buf, buf+5); // copy contents into it from buffer (I don't like this part)

И для работы мне нужно было определить

_ITERATOR_DEBUG_LEVEL=0

потому что изначально он установлен в 2 и фактически выполняет проверку отладки (я думаю) Это не определено в режиме выпуска, верно? Так что это мой обходной путь, я хотел бы заставить ppl удалить вектор в долгосрочной перспективе ... Так, ребята, что вы думаете об этом решении? А опасности ты видишь?


Мне действительно нужно сериализовать вектор с помощью memcpy. Я хочу сериализовать весь мой класс (например, сделать снимок памяти) и записать его в файл, а при перезагрузке прочитать его из файла и восстановить объект как без вызова его конструктора и использования оператора new.

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

copy (buf, buf + 5 myVvector.begin ());

Ну, это тоже не работает, так как я не использую ключевое слово new в своем классе, этот вектор, насколько я понимаю, не инициализирован. Так что, если я попытаюсь скопировать, push_back_fill этот вектор с smt, это выдаст мне эту ошибку:

Необработанное исключение в 0x00ec455b в newDel.exe: 0xC0000005: Место чтения нарушения прав доступа 0x00654b4c.

что имеет смысл ... Кто-нибудь знает, как я могу вызвать конструктор / инициализатор вектора извне?

Ответы [ 6 ]

4 голосов
/ 21 октября 2010

Если у вас было

vector<char> foo;

foo.push_back( 'v' );
foo.push_back( 'e' );
foo.push_back( 'c' );
foo.push_back( 't' );
foo.push_back( 'o' );
foo.push_back( 'r' );

char *c = &foo[0];

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

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

Вы можете делать то, что вы хотите следующим образом:

copy( c, c+6, back_inserter( myVector ) );

это вызов copy из algorithm и вызов функции back_inserter из iterator.

3 голосов
/ 21 октября 2010

Нет стандартного способа сделать это. Вы можете изучить конкретную реализацию и посмотреть, как с этим справиться (хотя на самом деле пути не может быть), но ваш трюк может потерпеть неудачу, если ваша библиотека была изменена или обновлена. Авторы библиотеки, как правило, не чувствуют необходимости поддерживать такое использование.

vector<> - контейнерный класс. Это не оболочка для массива в стиле C, хотя она поддерживается внутри. Его поведение и производительность определяются Стандартом, но не его внутренними компонентами (за исключением того, что его содержимое должно храниться в непрерывной памяти). Авторы библиотеки пользуются этой свободой, чтобы создавать лучшие реализации, какие только могут.

Предположим, вы можете назначить внутренний указатель. Это, несомненно, указывает на память из свободного хранилища, но может не указывать на начало памяти, возвращаемое значение из new или malloc(). Размер памяти должен быть как минимум достаточным, чтобы вместимость умножалась на размер элементов, но на самом деле она может быть больше. vector<> может полагаться на то, что его содержимое является частью определенного пула или выделено и освобождено определенным образом. Распределение может повлиять на другие элементы данных vector<>, например, указатель на .end(). В любом из этих случаев вы не можете самостоятельно управлять памятью и переменными, не зная точной реализации.

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

0 голосов
/ 21 октября 2010

Я видел твой собственный ответ (который, кстати, не должен публиковаться как ответ, он должен был быть отредактирован в вопросе). Итак, вы хотите сделать сериализацию в C ++. Откажитесь от memcpy и используйте соответствующие средства сериализации, такие как boost :: serialization. Это не приятно, но это необходимо. В противном случае он просто не будет работать - C ++ не работает таким образом.

0 голосов
/ 21 октября 2010

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

0 голосов
/ 21 октября 2010

Вам это пригодится?

vector<char*> v;
char* c = { 'v', 'e', 'c', 't', 'o', 'r' };  
v.push_back(c);
0 голосов
/ 21 октября 2010

Если это "внутреннее", то, вероятно, не вмешиваться!

...