mpz_t的浅拷贝

10
GMP提供了初始化和赋值mpz_t的方法。调用mpz_init_set(a, b)将会将b的内容赋值给a。然而,我认为这会对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() { }
}

v=x; 是什么意思? - Jannes Braet
@JannesBraet,这个问题已经很久了,但我认为在那个时候这种语法要么不可用,要么不被鼓励使用。 - James
听起来在C++11中,你可以使用mpz_class的移动赋值(如果你在之后清除rhs,你不想要一个浅拷贝,你想要传输资源)。 - Marc Glisse
1个回答

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];

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() { }
}

但是需要注意的是,如果在删除浅拷贝之前删除原始的mpz,例如使用mpz_clear,那么mp_limb_t *_mp_d中的内容就会消失,浅拷贝中的指针也将不再有效,因此访问它可能会导致问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接