Сохранить номера GMP / MPIR в QList

#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 по двум причинам.

  1. типы mpz_t похожи на указатель, но вы не можете использовать новые
  2. 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();
}