C++ 通过使用(某种程度上)全局变量与静态函数变量初始化值?
在整个代码中,我需要一些小的助手函数。 要工作,它们需要用一些数据初始化一次。 我应该在哪里存储init数据 我想出了两种方法: 我在helper.cpp文件的范围内创建静态变量,我使用专用的setter函数设置该文件,然后在helper函数中使用它C++ 通过使用(某种程度上)全局变量与静态函数变量初始化值?,c++,c,static,initialization,global-variables,C++,C,Static,Initialization,Global Variables,在整个代码中,我需要一些小的助手函数。 要工作,它们需要用一些数据初始化一次。 我应该在哪里存储init数据 我想出了两种方法: 我在helper.cpp文件的范围内创建静态变量,我使用专用的setter函数设置该文件,然后在helper函数中使用它 static int _initData = 0; void initHelpMe(int initData) { _initData = initData; } void helpMe() { doSomethingWith(
static int _initData = 0;
void initHelpMe(int initData)
{
_initData = initData;
}
void helpMe()
{
doSomethingWith(_initData);
}
或者我在原始的helper函数中使用一个静态函数变量和一个默认参数
void helpMe(int initData = 0)
{
static int _initData = 0;
if (initData != 0)
_initData = initData;
doSomethingWith(_initData);
}
(让我确认0超出了initData的有效数据范围,并且我没有显示额外的代码,以确保在首次调用函数而不首先启动它时引发错误。)
这两种方法的优点/缺点是什么?还有更好的方法吗
我当然喜欢第二种方法,因为它将所有功能保留在一个地方。但我已经知道它不是线程安全的(这在上午不是问题)
<>和,使这更有趣,虽然是C++,但这不是在面向对象中使用,而是在过程代码中使用。因此,请不要回答提出对象或类的问题。想象一下,它是C++的语法。 < p>我建议你把你的数据打包成一个对象,直到我意识到你在用C++标签请求C解决方案……p> 两种解决方案都有各自的优点 第二个是我更喜欢的,假设我们只看“它看起来像什么/可维护性”。但是,如果使用
initData==0
多次调用helpMe
,则有一个缺点,因为在第一种情况下不存在额外的if
。如果doSomethingWith()
函数足够长,并且/或者编译器能够内联helpMe
(并且initData
是常量),则这可能是问题,也可能不是问题
当然,代码中的某些内容也必须调用initHelpMe
,因此结果可能是一样的
总而言之:基于隔离/封装,我更喜欢第二个。我显然更喜欢第二个!不同编译单元中的全局静态数据是按未指定的顺序初始化的(尽管是按一个单元的顺序)。函数的本地静态数据在第一次调用时初始化 示例: 如果您有两个翻译单元A和B。单元A在初始化期间调用单元B的函数helpMe。假设初始化顺序为A,B。 第一个解决方案将零初始化_initData设置为某些initData。之后,单元B的初始化将_initData重置回零,并可能产生内存泄漏或其他危害 还有第三种解决方案:
void helpMe(int initData = 0)
{
static std::once_flag once;
static int _initData = 0;
std::call_once(once, [&] {
_initData = initData;
}
doSomethingWith(_initData);
}
我对这两方面都有强烈的感觉
首选隔离2,但选项1将其移植到C++类。我用两种方法编码。它可以归结为软件架构
让我再提一点 两个选项都有缺点:您没有将初始化限制为一次。“需要用一些数据初始化一次”。OP的条件似乎确保正确初始化initHelpMe(123)
或HelpMe(123)
,然后是HelpMe()
,但不阻止/检测二次初始化
如果需要防止/检测二次故障,可以使用一些附加代码
// Initialization
if (_initData != 0) {
; // Handle error
}
_initData = initData;
我使用的另一个范例如下。它可能无法在您的代码中实现,因为它不作为参数传递
initData
,但可以神奇地获得它
void helpMe(void) {
static int Initialized = 0;
if (!Initialized) {
Initialized = 1;
_initData = initData();
}
doSomethingWith(_initData);
}
第三种解决方案仅限于C++11,对吗?我知道至少lambda函数是这样的,但我不确定std::call_once本身。执行重新初始化的选项实际上是代码的一个受欢迎的特性。每次都将initData作为参数也是一个选项,但不实用,因为函数在整个代码中都使用,我需要传递initData。我之所以不使用简单的全局变量,是因为避免了一些神奇的事情发生,所以代码需要“至少用一些数据初始化一次”。知道了。