理解函数返回

时间:2014-01-04 03:12:54

标签: c++ callstack armadillo

我是一名新手程序员,并且只简要介绍了函数调用的解剖结构(设置堆栈等)。我可以用两种不同的方式编写一个函数,我想知道哪个(如果有的话)效率更高。这是一个有限元程序,所以这个函数可以调用几千次。它使用的是线性代数库Aramdillo。

第一种方式:

void Q4::stiffness(mat &stiff) 
{
    stiff.zeros; // sets all elements of the matrix to zero
    // a bunch of linear algebra calculations
    // ...
    stiff *= h;
}

int main()
{
    mat elementStiffness(Q4__DOF, Q4__DOF);
    mat globalStiffness(totalDOF, totalDOF);
    for (int i = 0; i < reallyHugeNumber; i++)
    {
        elements[i].stiffness(&elementStiffness, PSTRESS);
        assemble(&globalStiffness, &elementStiffness);
    }
    return 0;
}

第二种方式:

mat Q4::stiffness() 
{
    mat stiff(Q4__DOF, Q4__DOF); // initializes element stiffness matrix
    // a bunch of linear algebra calculations
    // ...
    return stiff *= h;
}

int main()
{
    mat elementStiffness(Q4__DOF, Q4__DOF);
    mat globalStiffness(totalDOF, totalDOF);
    for (int i = 0; i < reallyHugeNumber; i++)
    {
        elementStiffness = elements[i].stiffness(PSTRESS);
        assemble(&globalStiffness, &elementStiffness);
    }
    return 0;
}

我认为我要问的是:使用第二种方式将mat stiff推送到堆栈然后复制到elementStiffness?因为我认为矩阵被推入堆栈然后被复制比传递矩阵是参考并将其元素设置为零要昂贵得多。

2 个答案:

答案 0 :(得分:3)

通过引用传递变量并对该变量进行计算要便宜得多。当c ++返回一个变量时,它几乎会复制两次。

首先在函数内部,然后调用复制构造函数或赋值运算符,具体取决于是将值赋给新变量还是现有变量,以初始化变量。如果你有一个带有很长内部状态变量列表的用户定义变量,那么这个赋值操作将占用运算符处理时间的很大一部分。

编辑#1:我忘记了c ++ 11和std :: move。许多编译器可以优化这样的函数,这样他们就可以使用std :: move而不是复制lvaue,它可以复制一个只是内存位置的rvalue。

答案 1 :(得分:0)

从表面上看,我认为第二种方式会更昂贵,因为它构建一个新的垫子并在每次调用时将其复制到堆栈中。当然,这取决于垫子结构在第一种方式中发生的频率。

那就是说,我认为最好的办法是设置一个实验和测试以确保(同意研究的建议)。