返回特征矩阵和临时矩阵

Returning Eigen matrices and temporaries

考虑以下函数Foo

// ...

Eigen::Vector3d Foo() {
    Eigen::Vector3d res;
    // ...
    return res;
}

int main () {
    Eigen::VectorXd foo = Foo();    // (1)
    return 0;
}

由于 return 值优化,行 (1) 不应创建任何临时文件。但请考虑以下情况:

// ...

int main () {
    Eigen::VectorXd foo;
    // ...
    foo.head<3>() = Foo();    // (2)
    return 0;
}

(2) 是否创建任何临时文件?更一般地说,像 (2) 中那样初始化矩阵的任何块是否会创建任何临时对象? 如果不是这种情况就太好了。否则,我可以重新定义 Foo 如下:

// ...

void AlternativeFoo(Eigen::Ref<Eigen::Vector3d> res) {
    // Modify res
}

int main () {
    Eigen::VectorXd foo;
    // ...
    AlternativeFoo(foo.head<3>());    // (3)
    return 0;
}

(3)是在不创建临时对象的情况下实现上述目标的唯一方法吗?

The line (1) should not create any temporaries due to return value optimization.

不,它必须为 Foo 的 return 值临时实现。

Foo 的 return 类型和变量 foo 的类型不匹配(直到 cv 限定):Vector3d vs VectorXd.

但这是允许复制省略的必要条件。 如果不是这种情况,则使用的构造函数首先既不是副本也不是移动构造函数。

所以省略不会发生,在将要调用的构造函数中,Foo 的 return 值绑定到引用参数,这将导致临时对象的具体化。

Does (2) create any temporaries? More generally, does initializing any block of a matrix as in (2) create any temporaries?

是的,Foo return 值的临时值将再次具体化,这次是由于绑定到 operator=.

中的引用参数引起的

Is (3) the only way to achieve the above without creating temporaries?

我想是的,但这可能并不重要。 假设 Foo 可以内联,这种区别可能会变得毫无意义,编译器将确定 Foo 中的操作是否可以直接在 foo 的存储上执行。

如果 Foo 无法内联,则复制向量的三个条目不太可能与函数调用有显着关联。在这种情况下,您的替代解决方案会强制执行额外的间接寻址,这可能比复制一些值的成本更高。