问题:
我有一些被调用很多的函数。在每个函数内部,构造局部变量。这些变量通常Eigen::MatrixXd
有点小(通常低于 10 x 10(。每次调用都会一遍又一遍地构造相同的变量,然后丢弃它。
我开始认为在函数之外定义这些变量,然后查找它们会更快。
- 为什么"查找"某个全局变量可能比一遍又一遍地重建它更快?
- 我应该将全局常量放在命名空间中吗?这种方法可能出现什么问题?
第一个代码:
我从这三个文件开始。
第一:functions.h
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
#include <Eigen/Dense>
Eigen::MatrixXd getMatrix();
#endif //FUNCTIONS_H
第二:functions.cpp
#include "functions.h"
Eigen::MatrixXd getMatrix()
{
Eigen::MatrixXd myMatrix(4,4);
for(int i = 0; i < 4; ++i)
{
myMatrix(i,i) = 3.0;
}
return myMatrix;
}
三、main.cpp
#include "functions.h"
int main()
{
for(int i = 0; i < 500000; ++i)
getMatrix();
return 0;
}
第二个代码:
首先,functions2.h
:
#ifndef FUNCTIONS2_H
#define FUNCTIONS2_H
#include <Eigen/Dense>
extern const Eigen::MatrixXd myMatrix;
Eigen::MatrixXd getMatrix2();
#endif //FUNCTIONS2_H
然后functions2.cpp
#include "functions2.h"
const Eigen::MatrixXd myMatrix = Eigen::MatrixXd::Identity(2,2);
Eigen::MatrixXd getMatrix2()
{
return myMatrix;
}
然后是不同的main.cpp
#include "functions2.h"
int main()
{
for(int i = 0; i < 500000; ++i)
getMatrix2();
return 0;
}
如果您的get
函数将始终返回相同的矩阵,则可以在第一次需要时生成一次矩阵,而无需使用全局变量,方法是使用静态局部矩阵。
Eigen::MatrixXd getMatrix()
{
static Eigen::MatrixXd myMatrix{[](){
Eigen::MatrixXd m(4,4);
for(int i = 0; i < 4; ++i)
{
m(i,i) = 3.0;
}
return m;
}};
return myMatrix;
}
这使用 lambda 函数而不是另一个函数来初始化矩阵。 它还会在每次创建矩阵的副本,但原始矩阵对所有用户都是隐藏的,无法更改。 复制省略在这里不能发生,因为源不是非静态局部变量。 RVO 仍然可以完成。
此处的另一个选项是返回对矩阵的引用,方法是将函数更改为
const &Eigen::MatrixXd getMatrix()
这将避免复制,并且仍然隐藏原始矩阵不被更改,除非调用方对返回值应用const_cast
。
对于getMatrix2
,您可以将您拥有的全局变量作为静态变量移动到getMatrix2
中。
一般
- 假设将矩阵
写入内存需要 1 秒,读取矩阵需要 1 秒钟。如果您使用全局变量或 main 中的变量编写一次,并且读取 N 次,则需要 1 + N*1 秒。如果每次要使用它时都重新创建对象,则需要 2*N 秒。
将常量放在对它们有意义的命名空间中可能是一个很好的设计决策。例如,也许你会把"pi"放在你的数学命名空间中。您应该将全局常量放在C++程序中的什么位置?
全局变量很可能更慢。
这可能有点令人惊讶,但通常从零封开始是便宜的。全局变量的缺点是所有代码都可能更改它们,这可能会妨碍优化。