查找全局变量,而不是在 c++ 函数中构造它们

Looking up global variables instead of constructing them inside a c++ function

本文关键字:函数 c++ 全局变量 查找      更新时间:2023-10-16

问题:

我有一些被调用很多的函数。在每个函数内部,构造局部变量。这些变量通常Eigen::MatrixXd有点小(通常低于 10 x 10(。每次调用都会一遍又一遍地构造相同的变量,然后丢弃它。

我开始认为在函数之外定义这些变量,然后查找它们会更快。

  1. 为什么"查找"某个全局变量可能比一遍又一遍地重建它更快?
  2. 我应该将全局常量放在命名空间中吗?这种方法可能出现什么问题?

第一个代码:

我从这三个文件开始。

第一: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 秒,读取矩阵需要 1 秒钟。如果您使用全局变量或 main 中的变量编写一次,并且读取 N 次,则需要 1 + N*1 秒。如果每次要使用它时都重新创建对象,则需要 2*N 秒。

  2. 将常量放在对它们有意义的命名空间中可能是一个很好的设计决策。例如,也许你会把"pi"放在你的数学命名空间中。您应该将全局常量放在C++程序中的什么位置?

全局变量很可能更慢。

这可能有点令人惊讶,但通常从零封开始是便宜的。全局变量的缺点是所有代码都可能更改它们,这可能会妨碍优化。