#qt4 #gmp #qlist
#qt4 #gmp #qlist
Вопрос:
Я пытаюсь написать программу на C с QT4.7 и библиотекой MPIR (v. 2.3.1). Во время некоторых вычислений мне нужно сохранить динамическое количество mpz_t (целочисленный тип хранилища) и для этого я хочу использовать QList или QVarLengthArray. Я успешно настроил базовый тест о том, как это сделать, но это выглядит настолько уродливо и явно неправильно, что я хочу попросить сделать это лучше.
Мой пример программы:
#include <QtCore/QCoreApplication>
#include <QList>
#include <qtimer.h>
#include <mpirxx.h>
#include <iostream>
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
QList<__mpz_struct> test;
std::cout << "Write ints 0 to 9 in the QList" << std::endl;
for (int i = 0; i < 10; i) {
mpz_t zahl;
mpz_init_set_si(zahl, i);
test.append(zahl[0]);
}
std::cout << "Check if everything is still there." << std::endl;
for (int i = 0; i < 10; i) {
mpz_t zahl;
zahl[0] = test.at(i);
std::cout << mpz_get_str(NULL, 10, zahl) << std::endl;
}
std::cout << "What an ugly hack." << std::endl;
QTimer::singleShot(0, amp;a, SLOT(quit()));
return a.exec();
}
(скомпилирован под Windows 7 / MSVC2010 SP1/QT4.7.3 /MPIR2.3.1)
Вывод правильный, но я сомневаюсь, что это допустимый или даже безопасный способ хранения mpz_t.
Пожалуйста, дайте мне знать, как этого добиться 🙂
Комментарии:
1. Почему вы думаете, что это небезопасно?
Ответ №1:
Если вы собираетесь использовать сохраненные данные во многих местах, передавать их между функциями и т.д., То я бы определенно использовал QList, поскольку они неявно разделяются.
Это позволяет выполнять множество приятных действий, таких как следующее:
void listOperation(QList<mpz_t> list)
{
// Initialize and set
mpz_t an_int;
mpz_init_set_si(an_int, 0);
list.append(an_int);
}
В этом коде мы передаем ‘list’ по значению, поэтому обычно происходит глубокое копирование (дублирование всех данных). Однако из-за неявного совместного использования выполняется только поверхностная копия (ссылочная копия; указатель на общий блок данных). Кроме того, даже если бы эта функция вызывалась очень часто, QList предварительно выделяет дополнительное пространство с обеих сторон своего внутреннего буфера, поэтому эта операция обычно будет O (1) (Взята из документации QList).
QList (и все контейнерные классы QT) подобны контейнерам std — они могут содержать объекты любого типа (даже примитивы и указатели).
Это становится сложным при использовании GMP по двум причинам.
- типы mpz_t похожи на указатель, но вы не можете использовать новые
- mpz_clear используется для очистки
Вероятно, лучшим подходом было бы использовать интерфейс класса. Таким образом, вы можете распределять свои объекты mpz_t как объекты mpz_class типичным способом c и не беспокоиться ни о чем.
mpz_class an_int = 1234;
mpz_class *another = new mpz_class(1234);
Обновленный пример:
(Не скомпилирован / протестирован)
#include <QtCore/QCoreApplication>
#include <QList>
#include <QDebug>
#include <qtimer.h>
#include <mpirxx.h>
#include <iostream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QList<mpz_class *> list;
qdebug() << "Write ints 0 to 9 in the QList";
for (int i = 0; i < 10; i)
{
test.append(new mpz_class(0));
}
qdebug() << "Check if everything is still there.";
foreach (mpz_class *item, list)
{
qdebug() << *item;
}
qdebug() << "Not so bad anymore.";
// Clean up list
qDeleteAll(list.begin(), list.end());
list.clear();
QTimer::singleShot(0, amp;a, SLOT(quit()));
return a.exec();
}