Хранить номера GMP/MPIR в 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, &a, SLOT(quit()));
    return a.exec();
}

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

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

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);
} 

В этом коде мы передаем "список" по значению, поэтому обычно происходит глубокое копирование (дублирование всех данных). Однако из-за неявного совместного использования происходит только поверхностное копирование (эталонная копия; указатель на общий блок данных). Кроме того, даже если бы эту функцию вызывали очень часто, 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();
}
Другие вопросы по тегам