C ++奇怪的行为与函数调用值

时间:2013-04-25 08:23:02

标签: c++ gsl

我有一个对象,它是GNU Scientific Library中的矩阵结构的类接口

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结构的完整副本(我猜)

编辑:

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

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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

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

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