Хранить номера GMP / MPIR в QList - PullRequest
0 голосов
/ 22 мая 2011

Я пытаюсь написать программу на 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, &a, SLOT(quit()));
    return a.exec();
}

(скомпилировано в Windows 7 / MSVC2010 SP1 / QT4.7.3 / MPIR2.3.1) Вывод правильный, но я сомневаюсь, что это верный или даже безопасный способ хранения mpz_t.

Пожалуйста, дайте мне знать, как этого добиться:)

1 Ответ

0 голосов
/ 26 мая 2011

Если вы собираетесь использовать свои хранимые данные во многих местах, передавать их между функциями и т. Д., Тогда я бы определенно использовал 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);
} 

В этом коде мы передаем «список» по значению, поэтому обычно происходит глубокое копирование (дублирование всех данных). Однако из-за неявного совместного использования происходит только поверхностное копирование (эталонная копия; указатель на общий блок данных). Кроме того, даже если бы эту функцию вызывали очень часто, QList предварительно выделяет дополнительное пространство по обеим сторонам своего внутреннего буфера, поэтому эта операция обычно будет O (1) (взято из документации QList ).

QList (и все контейнерные классы QT) похожи на контейнеры std - они могут содержать объекты любого типа (даже примитивы и указатели).

Это становится сложно при использовании GMP по двум причинам.

  1. Типы mpz_t похожи на указатели, но вы не можете использовать новые
  2. mpz_clear используется при очистке

Лучше всего было бы использовать интерфейс класса . Таким образом, вы можете выделять ваши объекты mpz_t как объекты mpz_class в типичном для С ++ стиле, и вам не придется о них беспокоиться.

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, &a, SLOT(quit()));
    return a.exec();
}
...