0

我正在尝试使用 QT4.7 和 MPIR 库(v. 2.3.1)用 C++ 编写程序。在某些计算过程中,我需要存储动态数量的 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的方式。

请让我知道如何实现这一目标:)

4

1 回答 1

0

If you are going to be using your stored data in lots of places, passing it between function, etc. then I would definitely use a QList as they are implicitly shared.

This allows for many nice things like the following:

void listOperation(QList<mpz_t> list)
{
    // Initialize and set
    mpz_t an_int;
    mpz_init_set_si(an_int, 0);
    list.append(an_int);
} 

In this code we are passing 'list' by value, so normally a deep copy (duplicating all data) would occur. However, because of the implicit sharing only a shallow copy (reference copy; pointer to a shared data block) occurs. Additionally, even if this function were to get called very frequently, a QList preallocates extra space on both sides of its internal buffer, so this operation will usually be O(1) (Taken from the QList) documentation.

A QList (and all of QT's container classes) are just like std containers--they can hold objects of any type (even primitives, and pointers).

This gets tricky when using GMP for two reasons.

  1. mpz_t types are pointer like, but you can't use new
  2. mpz_clear is used in cleanup

A better approach would probably be to use the class interface. That way you can allocate your mpz_t objects as mpz_class objects in the typical c++ fashion, and not have to worry about things.

mpz_class an_int = 1234;
mpz_class *another = new mpz_class(1234);

Updated example: (Not compiled/ tested)

#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();
}
于 2011-05-26T06:26:01.227 回答