2011-05-21 97 views
0

我想用QT4.7和MPIR库(v.2.3.1)在C++中编写程序。 在一些计算过程中,我需要存储动态数量的mpz_t(整数存储类型),并且希望使用QList或QVarLengthArray。我已经成功地做了一个关于如何做到这一点的基本测试,但看起来如此丑陋,显然是错误的,我想要求更好地做到这一点。将GMP/MPIR号码存储在QList中

我的示例程序:

#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

为什么你认为它不是安全的? – snoofkin 2011-05-22 08:37:04

回答

0

如果你是因为他们将要使用在很多地方你的存储数据,传递函数之间,等等,那么我肯定会使用的QList implicitly shared

这使得像下面的很多好东西:

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在清理

使用更好的方法很可能是使用class interface。这样你就可以将mpz_t对象以典型的C++方式分配为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(); 
}