如何从运行时参数初始化常量全局变量?

Posted

技术标签:

【中文标题】如何从运行时参数初始化常量全局变量?【英文标题】:How do I initialize a constant global variable from a runtime arguments? 【发布时间】:2021-05-18 20:44:24 【问题描述】:

因此,我在这里看到了有关如何通过提示用户输入然后使用cin 在运行时设置全局常量变量的问题。但是,我需要能够基于传递给 main 的参数之一(即来自argc/argv)设置一个常量全局变量。我发现的所有解决方案都涉及在 const 变量声明上方定义构造函数,但如果我只能从 main 访问 argcargv,这将不起作用。

这有可能吗?我该如何实现呢?

编辑:这是关于cin的问题,供参考:Are there any tricks to use std::cin to initialize a const variable?

【问题讨论】:

如果您需要使用运行时值更新全局常量,它如何? @specras 如果您看一下我刚刚引用的问题,您会发现实际上可以在运行时设置一次常量。重点是在程序运行时(基于传递的参数)正确设置该变量,然后被程序的其余部分视为常量。 你引用的问题没有设置全局常量。 @PatrickvD 我怀疑这是否可能以可移植的方式进行,至少不像字面上所说的那样。另一方面,如果您正在寻找特定于实现的解决方案,则可能有非标准方法可以在 main 之外访问 argcargv,这样就可以使用任何一个单例模式。 @PatrickvD> 实际上只有一个答案,它专门使用 std::cin,这是 C++ 标准的特殊情况,可用于全局初始化程序,而不会遇到初始化顺序惨败。这是一个非常特殊的边缘案例。 【参考方案1】:

全局范围内的对象被构​​造之前 main() 被调用,所以逻辑上不可能使用mainargcargv来建造它们。这是一个相当基本的先有鸡还是先有蛋的问题,没有可移植的解决方法。

可能会作弊并使用函数静态范围来模拟它,例如:

class MySingleton 
public:
    MySingle(int argc, char **argv);

    // ...


const MySingleton &global_singleton(int argc=0, char **argv=nullptr)

    static MySingleton instanceargc, argv;

    return instance;


int main(int argc, char **argv)

    global_singleton(argc, argv);

只要全局范围内没有其他任何东西在其构造函数中调用global_singleton,这可能会起作用。 main() 尽快完成,传入真正的argcargv,其他人只是调用它,默认无用参数。

【讨论】:

【参考方案2】:

无法在main 处初始化全局常量。当您的程序到达它时,所有全局变量必须已经初始化。

但是,可以编写一个包含值并且只允许设置一次的类。但是,检查必须在运行时完成。

类似这样的东西(std::optional 需要 C++17,但你不必使用它):

#include <optional>

template <typename T>
class LateConstant

public:
    LateConstant() = default;
    LateConstant(const LateConstant&) = delete;
    LateConstant& operator=(const LateConstant&) = delete;

    LateConstant& operator=(const T& x)
    
        if (!v.has_value())
        
            v = std::make_optional<T>(x);
        
        else
        
            std::terminate();
        

        return *this;
    

    bool has_value() const
    
        return v.has_value();
    

    const T& value() const
    
        return v.value();
    

private:
    std::optional<T> v;
;

这样,如果您尝试多次分配一个值,您的程序就会故意崩溃。它不是一个常数,但它可能仍然有用。

现在,老实说,您最好还是避免使用全局变量。在我被咬过几次之后,我已经多年没有使用它们了。如果您决定不使用全局变量,则可以改用常量局部变量,或者在类中收集您需要的数据并将其传递。

另一种可能性是使用类似的东西

int whatever(int i = 0)

    static const int stored = i;
    return stored;

如果您尝试多次设置它,它将忽略该值,这可能是个坏主意。

【讨论】:

以上是关于如何从运行时参数初始化常量全局变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何使全局常量的别名在C ++的变量

golang的flag包源码解析与使用

C语言中用const声明全局变量赋初值和不赋初值有何区别?变量存放位置有啥不一样?

如何获取 LLVM 全局变量常量值?

如何从 google-cloud-platform vminstance 中的 pubsub 回调函数调用全局变量?

PHP 常量PHP 变量全解析(超全局变量变量的8种数据类型等)