Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Копирование std::vector в void*, Как лучше копировать контейнеры 
V
    Опции темы
C/L
Дата 31.3.2009, 15:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 31.7.2004
Где: Самара

Репутация: нет
Всего: 1



Как лучше копировать контейнер vector. Есть специальные шаблонные функции, но они не всегда подходят, особенно если копировать в void указатель. Попробывал вот так:
Код

void TPRIMITIVE::Fill(void *dest){
    for(TVERTARR::iterator it = verts.begin(); it < verts.end(); it++){
        *(TVERTEX *)dest = *it;
        (TVERTEX *)(dest)++;
    }
}

пишет: error C2036: void *: неизвестный размер.
Может лучше подойдет memcpy?

Это сообщение отредактировал(а) C/L - 31.3.2009, 15:56
PM MAIL WWW ICQ   Вверх
zim22
Дата 31.3.2009, 16:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 29
Всего: 69



Цитата(C/L @  31.3.2009,  15:56 Найти цитируемый пост)
Может лучше подойдет memcpy?

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

можно так:
Код

void *p = GetPtr(); // p указывает на какую-то область с данными, подлежащими копированию
vector<unsigned char> vi(10); // вектор байтов.
memcpy(&vi.front(), p, vi.size()); 


Это сообщение отредактировал(а) zim22 - 31.3.2009, 16:16


--------------------
PM MAIL   Вверх
mrbrooks
Дата 31.3.2009, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 19
Всего: 306



C/L, попробуй через reinterpret_cast, не знаю правда, что получится  smile 
PM MAIL   Вверх
C/L
Дата 31.3.2009, 16:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 31.7.2004
Где: Самара

Репутация: нет
Всего: 1



Цитата(zim22 @  31.3.2009,  18:05 Найти цитируемый пост)
можно так:
Код

void *p = GetPtr(); // p указывает на какую-то область с данными, подлежащими копированию
vector<unsigned char> vi(10); // вектор байтов.
memcpy(&vi.front(), p, vi.size());

спасибо, попробую. Значит front() указывает на начало как и begin()?

Это сообщение отредактировал(а) C/L - 31.3.2009, 16:32
PM MAIL WWW ICQ   Вверх
InvalidProperty
Дата 31.3.2009, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

Репутация: 2
Всего: 9



Цитата(zim22 @ 31.3.2009,  16:05)
Цитата(C/L @  31.3.2009,  15:56 Найти цитируемый пост)
Может лучше подойдет memcpy?

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

можно так:
Код

void *p = GetPtr(); // p указывает на какую-то область с данными, подлежащими копированию
vector<unsigned char> vi(10); // вектор байтов.
memcpy(&vi.front(), p, vi.size()); 

Для memcpy третьим параметром нужно размер в байтах указывать, т.о. получается:
memcpy(&vi.front(), p, vi.size() * sizeof(unsigned char));
в данном случае, конечно, и так прокатывает, но вообще нужно знать.


--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
bsa
Дата 31.3.2009, 16:39 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



C/L, во-первых, по правилам положено проверять условие it != verts.end(). У всех итераторов есть оператор неравно, а вот оператор меньше - только у RandomAccessIterator.
во-вторых, в общем случае it++ выполняется дольше, чем ++it. Лучше используй префиксную форму, если тебе нет потребности в постфиксной.
в-третьих, можно писать так:
Код
std::copy(verts.begin(), verts.end(), std::back_inserter<TVERTEX>(static_cast<TVERTEX*>(dest)));
Хотя, лично я бы написал так:
Код
std::memcpy(dest, &*verts.begin(), sizeof(TVERTEX)*verts.size());

PM   Вверх
azesmcar
Дата 31.3.2009, 16:43 (ссылка) |   (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



Цитата

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

нельзя...нехорошо это

1. если используете memcpy, то используйте обыкновенный буфер. Не мешайте сишние функции с контейнерами, вы нарушаете инкапсуляцию.
2. it < verts.end() - это непереносимый код, используйте it != verts.end()
3. void* тоже штука нехорошая..

что конкретно надо сделать? может найдем другое решение?

Добавлено через 3 минуты и 7 секунд
неверно понял..тут копируем ИЗ контейнера а не В контейнер, тогда инкапсуляция не нарушается, но некрасиво все равно  smile 
PM   Вверх
vinter
Дата 31.3.2009, 17:15 (ссылка) |  (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



Цитата(bsa @  31.3.2009,  17:39 Найти цитируемый пост)
C/L, во-первых, по правилам положено проверять условие it != verts.end().

нет таких правил

Цитата(azesmcar @  31.3.2009,  17:43 Найти цитируемый пост)
2. it < verts.end() - это непереносимый код

вполне переносимый


--------------------
Мой блог
PM MAIL WWW   Вверх
bsa
Дата 31.3.2009, 17:22 (ссылка) |  (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(vinter @ 31.3.2009,  17:15)
Цитата(bsa @  31.3.2009,  17:39 Найти цитируемый пост)
C/L, во-первых, по правилам положено проверять условие it != verts.end().

нет таких правил

Имхо, это правило такое же, как "нельзя использовать goto". Т.е. для новичков. Когда набьет руку, то уже сам сообразит, что и когда использовать.
PM   Вверх
azesmcar
Дата 31.3.2009, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



vinter оператор < работает только для RandomAccessIterator как и написал bsa. Непереносимый я сказал в том смысле что с другими контейнерами не работает..лучше в данном случает писать != (возможно термин не тот подобрал).
Такая рекомендация описана толи у Майерся, то ли у Сатера.

Добавлено через 1 минуту и 22 секунды
Цитата

Имхо, это правило такое же, как "нельзя использовать goto". Т.е. для новичков. Когда набьет руку, то уже сам сообразит, что и когда использовать.

 smile
но в данном случае его лучше вообще не использовать, в привычку войдет
PM   Вверх
vinter
Дата 31.3.2009, 17:34 (ссылка) |  (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



Цитата(azesmcar @  31.3.2009,  18:23 Найти цитируемый пост)
Непереносимый я сказал в том смысле что с другими контейнерами не работает

Цитата(azesmcar @  31.3.2009,  18:23 Найти цитируемый пост)
Такая рекомендация описана толи у Майерся, то ли у Сатера.

А еще у Майерса написано, что ни в коем случе не стоит пытаться писать универсально-контейнерный код, я с ним в этом полностью солидарен. 
Цитата(azesmcar @  31.3.2009,  18:23 Найти цитируемый пост)
но в данном случае его лучше вообще не использовать, в привычку войдет

в этом нет ничего плохого, я периодически использую именно такую запись. Проблем пока не видел. 
Я правда не хотел придираться, просто не надо подавать эту рекомендацию как аксиому.


--------------------
Мой блог
PM MAIL WWW   Вверх
azesmcar
Дата 31.3.2009, 17:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



Цитата

А еще у Майерса написано, что ни в коем случе не стоит пытаться писать универсально-контейнерный код, я с ним в этом полностью солидарен. 

не совсем так, он говорит что пытатся написать контейнерно независимый код, часто приводит к неэффективности, но в этом случае - мы ничего не делаем чтобы сделать его контейнеро-независимым..так что, по моему все таки лучше != 
PM   Вверх
C/L
Дата 1.4.2009, 07:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 31.7.2004
Где: Самара

Репутация: нет
Всего: 1



Цитата(bsa @  31.3.2009,  18:39 Найти цитируемый пост)
C/L, во-первых, по правилам положено проверять условие it != verts.end(). У всех итераторов есть оператор неравно, а вот оператор меньше - только у RandomAccessIterator.

Как я понимаю ошибка в моем случае произойдет только если я поменяю тип контейнера например на list, так как у него нет RandomAccessIterator, но тогда и memcpy() не будет работать - это тоже непереносимый код. Или возможны и другие проблемы в использовании оператора <?

Цитата(bsa @  31.3.2009,  18:39 Найти цитируемый пост)
во-вторых, в общем случае it++ выполняется дольше, чем ++it. Лучше используй префиксную форму, если тебе нет потребности в постфиксной.

спасибо, учту.

Цитата(azesmcar @  31.3.2009,  18:43 Найти цитируемый пост)
что конкретно надо сделать? может найдем другое решение?

Вот и я думаю, может без копирования можно как то обойтись. Мне нужно заполнить буфер вершин, переданный устройством по указателю void*. Может можно построить вектор прямо в буфере? При этом при необходимости передать контейнеру указатель на CALLBACK функцию, изменяющую размер буфера. Для этого наверно придется свой контейнер писать... smile 

Это сообщение отредактировал(а) C/L - 1.4.2009, 07:47
PM MAIL WWW ICQ   Вверх
azesmcar
Дата 1.4.2009, 08:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



Цитата

Как я понимаю ошибка в моем случае произойдет только если я поменяю тип контейнера например на list, так как у него нет RandomAccessIterator, но тогда и memcpy() не будет работать - это тоже непереносимый код. Или возможны и другие проблемы в использовании оператора <?

согласен..просто чтобы привычка не выработалась..речь об общем случае.

Цитата

Вот и я думаю, может без копирования можно как то обойтись. Мне нужно заполнить буфер вершин, переданный устройством по указателю void*. Может можно построить вектор прямо в буфере? При этом при необходимости передать контейнеру указатель на CALLBACK функцию, изменяющую размер буфера. Для этого наверно придется свой контейнер писать... smile 

Код

std::copy(vec.begin(), vec.end(), reinterpret_cast<VERTEX*>(buf) );

а вот так не пойдет?
PM   Вверх
xvr
Дата 1.4.2009, 10:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Если то, что копируется не является POD или структурой/юнионом из POD'ов (без конструктора, деструктора и виртуальных методов), то memcpy использовать нельзя  smile 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0937 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.