使用静态成员函数初始化初始化列表中的常量成员变量有什么问题吗?

Are there any problems in using a Static Member Function to initialize a Constant Member Variable in an Initializer List?

我希望在我的程序中有一个 class 直接从 main 方法获取命令行参数。我希望这些信息中的一些对于 Class 是恒定的,但也取决于输入的命令行参数。

我在这里阅读了详细的答案: C++ defining a constant member variable inside class constructor , 不过我还是有点糊涂...

main.cpp:

#include "Launcher.h"

int main(int argc, char *argv[]) {
    Launcher launcher(argc, argv);

    // do other stuff with launcher

    return 0;
}

Launcher.h:

#ifndef LAUNCHER_H
#define LAUNCHER_H

#include <string>
#include <vector>

class Launcher {
public:
    Launcher(int, char *[]);

private:
    const int argumentCount;
    const std::vector<std::string> arguments;

    static const std::vector<std::string> INIT_arguments(int, char *[]);
};

#endif

Launcher.cpp

#include "Launcher.h"

Launcher::Launcher(int inputCount, char *inputArguments[]) :
    argumentCount(inputCount),
    arguments(INIT_arguments(inputCount, inputArguments))
{}

Launcher::INIT_arguments(int inputCount, char *inputArguments[]) {
    std::vector<std::string> argumentVector;
    for (int i = 0; i < inputCount; i++) {
        std::string currentArgument = inputArguments[i];
        argumentVector.push_back(currentArgument);
    }
    return argumentVector;
}

(我知道在这个例子中可能有替代方法通过不使用初始化列表来实现相同的结果。在其他情况下我使用复杂的函数来确定 const 变量的值但是选择这个简单的例子来演示这个概念。)

我的问题是:

  1. 使用静态函数初始化const成员变量有什么问题吗(在上面的例子中)?
  2. 如果用于初始化 const 变量的函数是非静态的,是否有任何变化/是否还有更多问题?
  3. 在头文件中定义函数及其声明与在头文件中声明然后在源文件中定义函数之间有什么区别吗? static/non-static有什么区别吗?
  4. 与一般问题无关,但是...是否有通过引用传递 char *[] 变量的简单方法或者更有效的方法?

Are there any problems with initializing a const member variable by using a static function(In the example above)?

没有。有人可能会争辩说,这样一个与您的实际 class 几乎没有关系的本地辅助函数可以外包到 helper/utility 实体中,也许是匿名名称空间或其他地方的自由函数(模板)(使其可测试)。

Does anything change / are there any more problems if the function used to initialize the const variable is non-static?

使其成为static 确保成员函数与任何实例的状态无关(显然,自由函数也是如此)。对于用于初始化状态的函数,我肯定会保持这种方式。

Is there any difference between defining the function in the header file alongside its declaration versus how its been declared in the header file then defined in the source file?

没有。如果你想让它成为一个免费功能,你需要处理可能的 ODR 违规行为,并且至少将其标记为 inline.

Is there an easy way to pass the char *[] variable by reference or perhaps a more efficient way?

有一种更有效的方法,即根本不使用该函数,而是依赖以两个迭代器作为参数的 std::vector constructor(重载 #4)。指向同一个原始数组的指针在这里没问题,所以你可以这样做:

Launcher::Launcher(int inputCount, char *inputArguments[]) :
   argumentCount(inputCount),
   arguments(inputArguments, inputArguments + inputCount) {}

另请注意,Launcher 似乎并不打算修改命令行参数。在这种情况下,您根本不必复制字符串。使用 std::string_view 代替(如果 C++17 可用)或将其保留为 const char*(命令行参数的一个好处是您不必考虑它们的生命周期)。