如何从运行时参数初始化常量全局变量?
How do I initialize a constant global variable from a runtime arguments?
所以,我在这里看到了关于如何通过提示用户输入然后使用 cin
在运行时设置全局常量变量的问题。但是,我需要能够根据传递给 main 的参数之一(即来自 argc
/argv
)设置一个常量全局变量。我发现的所有解决方案都涉及在 const 变量声明上方定义构造函数,但如果我只能从 main.
访问 argc
和 argv
,这将不起作用
这可能吗?我该如何实施?
编辑:这里是讲cin
的问题,供参考:Are there any tricks to use std::cin to initialize a const variable?
全局范围内的对象在main
()被调用之前构建,所以逻辑上不可能使用main
的 argc
和 argv
来构造它们。这是一个相当基本的先有鸡还是先有蛋的问题,没有可移植的解决方法。
可能可以作弊并使用函数静态作用域来模拟它,例如:
class MySingleton {
public:
MySingle(int argc, char **argv);
// ...
}
const MySingleton &global_singleton(int argc=0, char **argv=nullptr)
{
static MySingleton instance{argc, argv};
return instance;
}
int main(int argc, char **argv)
{
global_singleton(argc, argv);
}
只要全局作用域中没有其他内容在其构造函数中调用 global_singleton
,这可能会起作用。 main()
尽快完成,传入真实的 argc
和 argv
,其他人只是使用默认的无用参数调用它。
无法在 main
处初始化全局常量。当您的程序到达它时,所有全局变量都必须已经初始化。
但是,可以编写一个 class 包含一个值并且只允许您设置一次。但是,必须在运行时进行检查。
类似这样的东西(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;
};
有了这个,如果您尝试多次分配一个值,您的程序就会故意崩溃。它不是一个常量,但它可能仍然有用。
现在,老实说,您最好还是避免使用全局变量。在我被咬了好几次之后,我已经好几年没用过它们了。如果您决定不使用全局变量,则可以改用常量局部变量,或者在 class 中收集您需要的数据并将其传递。
另一种可能性是使用类似
的东西
int whatever(int i = 0)
{
static const int stored = i;
return stored;
}
如果您尝试多次设置它,它只会忽略该值,这可能是个坏主意。
所以,我在这里看到了关于如何通过提示用户输入然后使用 cin
在运行时设置全局常量变量的问题。但是,我需要能够根据传递给 main 的参数之一(即来自 argc
/argv
)设置一个常量全局变量。我发现的所有解决方案都涉及在 const 变量声明上方定义构造函数,但如果我只能从 main.
argc
和 argv
,这将不起作用
这可能吗?我该如何实施?
编辑:这里是讲cin
的问题,供参考:Are there any tricks to use std::cin to initialize a const variable?
全局范围内的对象在main
()被调用之前构建,所以逻辑上不可能使用main
的 argc
和 argv
来构造它们。这是一个相当基本的先有鸡还是先有蛋的问题,没有可移植的解决方法。
可能可以作弊并使用函数静态作用域来模拟它,例如:
class MySingleton {
public:
MySingle(int argc, char **argv);
// ...
}
const MySingleton &global_singleton(int argc=0, char **argv=nullptr)
{
static MySingleton instance{argc, argv};
return instance;
}
int main(int argc, char **argv)
{
global_singleton(argc, argv);
}
只要全局作用域中没有其他内容在其构造函数中调用 global_singleton
,这可能会起作用。 main()
尽快完成,传入真实的 argc
和 argv
,其他人只是使用默认的无用参数调用它。
无法在 main
处初始化全局常量。当您的程序到达它时,所有全局变量都必须已经初始化。
但是,可以编写一个 class 包含一个值并且只允许您设置一次。但是,必须在运行时进行检查。
类似这样的东西(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;
};
有了这个,如果您尝试多次分配一个值,您的程序就会故意崩溃。它不是一个常量,但它可能仍然有用。
现在,老实说,您最好还是避免使用全局变量。在我被咬了好几次之后,我已经好几年没用过它们了。如果您决定不使用全局变量,则可以改用常量局部变量,或者在 class 中收集您需要的数据并将其传递。
另一种可能性是使用类似
的东西int whatever(int i = 0)
{
static const int stored = i;
return stored;
}
如果您尝试多次设置它,它只会忽略该值,这可能是个坏主意。