mpz_t的浅拷贝

Jam*_*mes 5 gmp shallow-copy

GMP提供了初始化和分配mpz_t的方法.

对mpz_init_set(a,b)的调用将分配给b的内容.但是,我认为,这会对b执行深层复制.

在我的项目中,我需要使用长达5,000,000的mpz_t数组(我们正在谈论640MB的内存),我正在使用的框架对这些类型执行各种赋值操作(我没有开发框架和重写它不是一个选项).最近,我意识到在大多数赋值之后,b的值被清除,因此深度复制已经可以像它一样使用的值似乎是不自然的.但是,框架的接口不允许这样做(使用mpz_t周围的包装器)并且需要花费很多努力来改变它(我仍然可以改变一些基本的东西).

我已经尝试了一个基于指向mpz_class的指针的解决方案,但令人惊讶的是,它根本没有提供性能提升.实际上它会降低执行速度(尽管没有在大型阵列上测试).

我的问题是:我可以浅滩复制一个mpz_t吗?下面给出的例子

class somewrapper
{
    mpz_t v;
    somewrapper(mpz_t x)    //constructor: probably performing deep copy here as well
    {
        // the following line performs a deep copy(?) on x
        // but x is not used. why not shallow copy it?
        mpz_init_set(v, x);
    }
    somefunction() { }
}
Run Code Online (Sandbox Code Playgroud)

Arc*_*Arc 2

考虑这mpz_t是一个定义在的结构gmp.h:

typedef struct
{
  int _mp_alloc;        /* Number of *limbs* allocated and pointed to by the _mp_d field.  */
  int _mp_size;         /* abs(_mp_size) is the number of limbs the last field points to.  If _mp_size is negative this is a negative number.  */
  mp_limb_t *_mp_d;     /* Pointer to the limbs.  */
} __mpz_struct;

// ... 

typedef __mpz_struct mpz_t[1];
Run Code Online (Sandbox Code Playgroud)

GMP 开发人员将类型转换为大小为 1 的数组,因为这简化了将类型传递给函数,就像它是指针一样(请参见此处以获得详细解释)

所以你可以像这样制作一个浅拷贝mpz_t:

class somewrapper
{
    mpz_t v;
    somewrapper(mpz_t x)    //constructor: for sure passing the reference
    {
        // the following line performs a shallow copy
        v->_mp_alloc = x->_mp_alloc;
        v->_mp_size = x->_mp_size;
        v->_mp_d = x->_mp_d;
    }
    somefunction() { }
}
Run Code Online (Sandbox Code Playgroud)

但请注意,如果您mpz在删除浅副本之前删除原始副本,例如使用mpz_clear,那么 in 的汁液mp_limb_t *_mp_d将会消失,并且浅副本中的指针将不再有效,因此访问它可能会造成麻烦。