Russian Qt Forum
Май 18, 2024, 23:19 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Работа QVector  (Прочитано 10018 раз)
kadavr
Гость
« : Август 08, 2013, 12:27 »

Здравствуйте.

Если способ создать QVector так что бы он работал с уже существующим огромным массивом чисел без копирования. То есть у меня есть С либа которая генерит мне этот массив, но я не хочу работать в С стиле с указателями а хочу работать с этими данными как с вектором. Возможно ли это сделать не копирую блоки памяти? Массив может быть больше мегабайта.
Записан
gorec323
Гость
« Ответ #1 : Август 08, 2013, 12:35 »

У QVector есть функция
Код:
T *	data ()

Можно ее использовать.
Записан
kadavr
Гость
« Ответ #2 : Август 08, 2013, 12:40 »

но я ведь не могу заставить указывать этот указатель на мою область памяти, или могу?
Записан
kadavr
Гость
« Ответ #3 : Август 08, 2013, 12:49 »

Вот пример кода

Код:
pvector_info pinfo = ngGet_Vec_Info();

double * pMyVector = pinfo->v_realdata; //указатель на нужную область памяти

//хотелось бы что то на подобии этого
QVector<double> data(30000, pMyVector);  //!!! нет такого, а хочется

//а потом, например, отсортировать
sort(data);
   
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Август 08, 2013, 13:13 »

но я ведь не могу заставить указывать этот указатель на мою область памяти, или могу?
Не можете, контейнер распределяет память сам, нельзя подсунуть ему выделенное, можно только скопировать. Ну и работайте с С массивом, тот же sort.
Записан
gorec323
Гость
« Ответ #5 : Август 08, 2013, 13:14 »

Вот пример кода

Код:
pvector_info pinfo = ngGet_Vec_Info();

double * pMyVector = pinfo->v_realdata; //указатель на нужную область памяти

//хотелось бы что то на подобии этого
QVector<double> data(30000, pMyVector);  //!!! нет такого, а хочется

//а потом, например, отсортировать
sort(data);
   

Можно что-то вроде :
Код:
double * pMyVector = new double[30000];
QVector<double> data(30000);
data.data() = pMyVector;
Записан
twp
Гость
« Ответ #6 : Август 08, 2013, 13:19 »

Можно что-то вроде :
Код:
double * pMyVector = new double[30000];
QVector<double> data(30000);
data.data() = pMyVector;
Не сработает поскольку data() возвращает только указатель на данные, а чтоб модифицировать внутренний указатель QVector надо возвращать указатель на указатель.

ТС, А если ли возможность модифицировать C либу, чтоб передавать ей уже распределенную память?
Записан
kadavr
Гость
« Ответ #7 : Август 08, 2013, 13:55 »

Igors и twp спасибо за конкретные ответы.

Модифицировать либу нельзя(теоретически можно, исходники есть и лицензия BSD), но она сильно большая и сложная. В целом задача состоит в том чтобы ее С подобный API обернуть в более безопасный QT подобный, по этому оставлять роботу напрямую с ссылками будет не правильно. Думаю, что нужно писать свой класс Vector который будет внешне идентичен QVector но без возможности изменять размер. Или может быть дать пользователю доступ к памяти через QDataStream или QByteArray, а пользователь пусть сам думает что с ним делать. Но в любом случае, если дальше работать с этим массивом, то Qt захочет сделать копию, наверное этого не избежать. Может быть это не так и страшно, просто у меня контроллерное прошлое и мне плакать хочется когда понимаю что без видимой на то причины будут копироваться 10 мегабайт памяти.
Записан
kadavr
Гость
« Ответ #8 : Август 08, 2013, 14:07 »

Теперь не могу понять как скопировать массив в QVector без итераций?
Нашел такое решение:

Код:
    std::vector<double> tmpData;
    tmpData.assign(array, array + numberOfElementsInArray);
    myData.fromStdVector(tmpData);

Но здесь по моему аж два копирования(да и выглядит по идиотски), или Qt умнее чем я думаю и не станет копировать второй раз?
Записан
twp
Гость
« Ответ #9 : Август 08, 2013, 14:30 »

по идее один раз
Код
C++ (Qt)
static inline QVector<T> fromStdVector(const std::vector<T> &vector)
{ QVector<T> tmp; tmp.reserve(int(vector.size())); qCopy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; }
 
можно попробовать и так
Код
C++ (Qt)
myData.reserve(numberOfElementsInArray);
memcpy(myData.data(), array, sizeof(double) * numberOfElementsInArray);
 
Вообще QVector подчиняется imlicit shared, что означает копирование происходит, если вызывается не константный метод QVector и число ссылок на этот объект > 1
Записан
kadavr
Гость
« Ответ #10 : Август 08, 2013, 14:39 »

про  imlicit shared я читал, но на практике следующий код дает три разный блока памяти:


Код:
                    pvector_info pinfo = ngGet_Vec_Info(*currV);
   
                    std::vector<double> tmpData(pinfo->v_length);
                    tmpData.assign(pinfo->v_realdata, pinfo->v_realdata + pinfo->v_length);
                    QVector<double> data = QVector<double>::fromStdVector(tmpData);
   
                    double * newData = data.data();
                    double * newData2 = tmpData.data();
   
                    msgOut << "value : "  << data[0]<< endl;
                    msgOut << "value located  : "  << (long)pinfo->v_realdata << endl;
                    msgOut << "value 1 located  : "  << (long)newData << endl;
                    msgOut << "value 2 located  : "  << (long)newData2 << endl;

дают результат

Код:
value : 1.38062e-23
value located  : 6683232
value 1 located  : 6812160
value 2 located  : 6812112
Записан
twp
Гость
« Ответ #11 : Август 08, 2013, 14:53 »

все верно, std::vector выделил блок памяти у себя, QVector - у себя и соответственно было 2 копирования - в std::vector и в QVector. По идее через memcpy произойдет только одно быстрое копирование блока памяти.
Записан
kadavr
Гость
« Ответ #12 : Август 08, 2013, 14:54 »

сделал так:
Код:
                    pvector_info pinfo = ngGet_Vec_Info(*currV);

                    QVector<double> data(pinfo->v_length);
                    memcpy(data.data(), pinfo->v_realdata, pinfo->v_length * sizeof(double));

И успокоился, нужно двигаться дальше. Если будет нужно потом буду оптимизировать.

Всем большое спасибо.

И еще:
Записан
kadavr
Гость
« Ответ #13 : Август 08, 2013, 14:58 »

Извиняюсь не дописал.

Код:
myData.reserve(numberOfElementsInArray);
memcpy(myData.data(), array, sizeof(double) * numberOfElementsInArray);

Так работать не будет, так как была выделена память, но объекты не созданы и счетчик в QVector будет все равно равен нулю.
Записан
twp
Гость
« Ответ #14 : Август 08, 2013, 15:08 »

Вообще я не правильно указал метод, вместо reserve надо resize, что в принципе одно и тоже что QVector<double> data(size);
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.084 секунд. Запросов: 19.