2

我有一个对象,它是 GNU 科学库中的矩阵结构的类接口

typedef double real_t;
typedef unsigned short index_t;
class matrix
{
        gsl_matrix* m;
    public:
        matrix(index_t rows, index_t columns, real_t val);
}

matrix::matrix(index_t rows, index_t columns, real_t val)
{
    m=gsl_matrix_alloc(rows,columns);
    gsl_matrix_set_all(m, val);
    return;
}

index_t matrix::rows(void)
{
    return m->size1;
}

index_t matrix::columns(void)
{
    return m->size2;
}

问题是,如果我使用这样的函数按值获取矩阵对象:

void test_function(const matrix m){};

并在像这样的程序中使用它

int main()
{
    matrix m(4,4,1);
    cout << m.rows() << '\t' << m.columns() << endl;
    test_function(m);
    cout << m.rows() << '\t' << m.columns() << endl;
}

我惊讶地发现矩阵对象 m 的行数被函数修改test_function为垃圾值,即使我将关键字 const 放在参数之前并且调用是按值进行的。但最奇怪的是,如果我使用这样的函数,该函数利用引用调用:

void test_function(const matrix &m){};

什么都没有发生,一切似乎都很好。

据我所知,按值调用不应该能够修改函数的参数,特别是如果函数在这种情况下什么都不做,特别是如果我在函数原型中的参数名称之前显式使用关键字 const 。 ..

任何帮助将不胜感激。

编辑:

我还将矩阵类的复制构造函数定义为

matrix& matrix::operator= (const matrix& src)
{
    gsl_matrix_memcpy(m,src.m);
    return *this;
}

它做了 gsl_matrix 结构的完整副本(我猜)

编辑:

好吧,我想我终于明白了:按值调用函数创建了一个浅拷贝对象,其中只包含指向真实对象的指针,当 test_function 终止时,所有局部变量都被销毁,所以矩阵类的析构函数(定义但为简洁起见,此处省略)被调用,但是通过这种方式,主对象(本地 m 指向的对象)与局部变量一起被销毁。无论如何,我解决了定义一个正确的复制构造函数的问题执行对象的完整(深度)副本,然后使用引用调用,这对于繁重的计算应该更好。非常感谢大家的帮助!

4

2 回答 2

2

因为默认的copy ctor只是做一个浅拷贝,也就是说,它只是拷贝指针m的值,而不是分配一个新的。

于 2013-04-25T08:26:13.313 回答
1

当您按值传递参数时,编译器会调用单参数复制构造函数以在函数中创建值。如果您不提供复制构造函数,编译器会为您生成一个。

在上面的示例中,编译器生成的复制构造函数对内部矩阵指针进行浅拷贝。当函数中新生成的矩阵超出范围时,浅拷贝的指针也会被删除。我的猜测是这就是原因。

您可以通过提供不复制 gsl_matrix 指针的复制构造函数来检查这一点。

于 2013-04-25T08:34:14.763 回答