Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Для новичков > Копирование std::vector в void* |
Автор: C/L 31.3.2009, 15:56 | ||
Как лучше копировать контейнер vector. Есть специальные шаблонные функции, но они не всегда подходят, особенно если копировать в void указатель. Попробывал вот так:
пишет: error C2036: void *: неизвестный размер. Может лучше подойдет memcpy? |
Автор: zim22 31.3.2009, 16:05 | ||
попробуйте. может и лучше. ведь особенность вектора в том, что он располагает свои элементы в непрерывном блоке памяти и следовательно к нему можно применять сишные функции для работы с ней. можно так:
|
Автор: mrbrooks 31.3.2009, 16:07 |
C/L, попробуй через reinterpret_cast, не знаю правда, что получится ![]() |
Автор: InvalidProperty 31.3.2009, 16:32 | ||||
Для memcpy третьим параметром нужно размер в байтах указывать, т.о. получается: memcpy(&vi.front(), p, vi.size() * sizeof(unsigned char)); в данном случае, конечно, и так прокатывает, но вообще нужно знать. |
Автор: bsa 31.3.2009, 16:39 | ||||
C/L, во-первых, по правилам положено проверять условие it != verts.end(). У всех итераторов есть оператор неравно, а вот оператор меньше - только у RandomAccessIterator. во-вторых, в общем случае it++ выполняется дольше, чем ++it. Лучше используй префиксную форму, если тебе нет потребности в постфиксной. в-третьих, можно писать так:
|
Автор: azesmcar 31.3.2009, 16:43 | ||
нельзя...нехорошо это 1. если используете memcpy, то используйте обыкновенный буфер. Не мешайте сишние функции с контейнерами, вы нарушаете инкапсуляцию. 2. it < verts.end() - это непереносимый код, используйте it != verts.end() 3. void* тоже штука нехорошая.. что конкретно надо сделать? может найдем другое решение? Добавлено через 3 минуты и 7 секунд неверно понял..тут копируем ИЗ контейнера а не В контейнер, тогда инкапсуляция не нарушается, но некрасиво все равно ![]() |
Автор: vinter 31.3.2009, 17:15 | ||
нет таких правил вполне переносимый |
Автор: bsa 31.3.2009, 17:22 | ||||
Имхо, это правило такое же, как "нельзя использовать goto". Т.е. для новичков. Когда набьет руку, то уже сам сообразит, что и когда использовать. |
Автор: azesmcar 31.3.2009, 17:23 | ||
vinter оператор < работает только для RandomAccessIterator как и написал bsa. Непереносимый я сказал в том смысле что с другими контейнерами не работает..лучше в данном случает писать != (возможно термин не тот подобрал). Такая рекомендация описана толи у Майерся, то ли у Сатера. Добавлено через 1 минуту и 22 секунды
![]() но в данном случае его лучше вообще не использовать, в привычку войдет |
Автор: vinter 31.3.2009, 17:34 | ||||
А еще у Майерса написано, что ни в коем случе не стоит пытаться писать универсально-контейнерный код, я с ним в этом полностью солидарен.
в этом нет ничего плохого, я периодически использую именно такую запись. Проблем пока не видел. Я правда не хотел придираться, просто не надо подавать эту рекомендацию как аксиому. |
Автор: azesmcar 31.3.2009, 17:37 | ||
не совсем так, он говорит что пытатся написать контейнерно независимый код, часто приводит к неэффективности, но в этом случае - мы ничего не делаем чтобы сделать его контейнеро-независимым..так что, по моему все таки лучше != |
Автор: C/L 1.4.2009, 07:26 | ||||
Как я понимаю ошибка в моем случае произойдет только если я поменяю тип контейнера например на list, так как у него нет RandomAccessIterator, но тогда и memcpy() не будет работать - это тоже непереносимый код. Или возможны и другие проблемы в использовании оператора <?
спасибо, учту. Вот и я думаю, может без копирования можно как то обойтись. Мне нужно заполнить буфер вершин, переданный устройством по указателю void*. Может можно построить вектор прямо в буфере? При этом при необходимости передать контейнеру указатель на CALLBACK функцию, изменяющую размер буфера. Для этого наверно придется свой контейнер писать... ![]() |
Автор: azesmcar 1.4.2009, 08:36 | ||||||
согласен..просто чтобы привычка не выработалась..речь об общем случае.
а вот так не пойдет? |
Автор: xvr 1.4.2009, 10:34 |
Если то, что копируется не является POD или структурой/юнионом из POD'ов (без конструктора, деструктора и виртуальных методов), то memcpy использовать нельзя ![]() |
Автор: C/L 1.4.2009, 10:39 | ||
К сожалению не знаю что такое POD. Структура простая, но имеется конструктор, простой, никаких указателей он не инициализирует. Добавлено через 50 секунд Виртуальных методов тоже нету |
Автор: zim22 1.4.2009, 11:00 |
это встроенные типы данных. а не определённые пользователем. например int, long, double, long*, ... значит не подходит. т.к. конструктор занимает дополнительное место и memset "фурычить" не будет ![]() |
Автор: C/L 1.4.2009, 11:00 | ||||||||
вот vector на самом деле принимает 2 параметра, первый - тип элементов. А второй зачем?
|
Автор: azesmcar 1.4.2009, 11:03 |
C/L второй алокатор, если хочешь написать свое реаспределение памяти |
Автор: C/L 1.4.2009, 11:05 | ||||
правда ![]() Добавлено через 2 минуты и 11 секунд
А с его помощью можно построить вектор где угодно? Пробывал искать по этой теме, пока ничего не нашел. |
Автор: bsa 1.4.2009, 11:14 | ||
Лучше почитать http://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.html - там нет упоминаний об обычном конструкторе (только конструктор копирования). Кстати, рекомендую почитать что-нибудь про классы, так как на лицо непонимание внутренней организации объектов. |
Автор: azesmcar 1.4.2009, 11:14 | ||
чего чего?? сколько места занимает конструктор в памяти? Добавлено @ 11:16 C/L если в классе нет динамически инициализируемых обьектов, или обьекта, который динамически инициализирует переменные - спокойно можно использовать.. |
Автор: bsa 1.4.2009, 11:20 | ||||
Можно "где-угодно", но не "из-чего угодно". Т.е. аллокатор будет использоваться вместо оператора new. Думаю, тебе не это нужно. Тебе написали уже все возможные варианты. Ну есть еще вариант без копирования - возвращать константный указатель на первый элемент вектора. Но для этого придется менять функцию, так как в нынешнем виде она подразумевает только копирование. |
Автор: azesmcar 1.4.2009, 11:27 |
можно например написать алокатор который будет напрямую создавать твои обьекты в твоем void* буфере с помощью placement new. Но я не уверен что тебе это нужно.. |
Автор: bsa 1.4.2009, 11:32 | ||
так я о том же ![]() |
Автор: azesmcar 1.4.2009, 11:34 |
bsa ![]() я немного детализировал ![]() |
Автор: zim22 1.4.2009, 11:34 |
bsa, azesmcar по почкам просьба больно не бить, понял свою тупость про POD типы ![]() |
Автор: C/L 1.4.2009, 11:52 | ||||
А что в этом особенного? Аллокаторы я еще не писал ![]()
Об этом я еще не думал, надо попробывать. Всем спасибо, тему можно считать закрытой. |
Автор: bsa 1.4.2009, 13:06 | ||||
Только имей в виду, что этот указатель будет жить до тех пор, пока вектор жив и к нему не применяются методы, изменяющие размер в сторону увеличения (insert, push_back, resize, reserve, например, но есть исключения - читать документацию, в части об инвалидации итераторов). |