gpt4 book ai didi

c++ - 在程序启动时自动执行代码而不违反 ODR

转载 作者:行者123 更新时间:2023-12-01 14:47:31 35 4
gpt4 key购买 nike

我尝试编写一种简单的方法来在程序开始时自动执行代码(不使用不可移植的属性())。

我编写了以下代码,如果将 main() 之前编写的代码放在头文件中,我会问它是否确实违反了 ODR。
或者,内联函数和变量是否阻止了这种情况?
如果违反 ODR,是否会出现函数被调用两次的情况?

#include <iostream>

//-----

template <void(*init_function)()>
class execute_at_start
{
struct dummy final {};
~execute_at_start() = delete;
inline static dummy execute_() { init_function(); return dummy{}; }
inline static dummy auto_init_ = execute_();
};

//-----

inline void echo(){ std::cout << "echo" << std::endl; }

template class execute_at_start<&echo>;

int main()
{
std::cout << "EXIT SUCCESS" << std::endl;
return EXIT_SUCCESS;
}

先感谢您

最佳答案

您的解决方案应该是 ODR 安全的。 C++标准要求静态数据成员只有一个实例auto_init_对于 execute_at_start<> 的每个不同的实例化类模板并且它被初始化一次。

Itanium C++ ABI(除了 MSVC 之外,大多数编译器都遵守它)需要全局变量的保护变量(这里是 auto_init_)以确保它们被初始化一次:

If a function-scope static variable or a static data member with vague linkage (i.e., a static data member of a class template) is dynamically initialized, then there is an associated guard variable which is used to guarantee that construction occurs only once.



Itanium C++ ABI §2.8 Initialization Guard Variables更多细节。

此问题的另一个不依赖保护变量的标准 ODR 安全解决方案是 Schwarz Counter .自 C++ 诞生以来,它就被用于初始化标准流( std::cout 和 friend 们)。在此解决方案中 counter是一个具有外部链接的显式保护变量,它确保只有 execute_at_start 的第一次调用构造函数调用 init_function :
// Header begin.
#include <iostream>

template<void(*init_function)()>
class execute_at_start {
static inline int counter = 0;
public:
execute_at_start() {
if(!counter++)
init_function();
}
};

inline void echo() { std::cout << "echo" << std::endl; }

execute_at_start<echo> const execute_at_start_echo; // A copy in each translation unit.

// Header end.

int main() {}

关于c++ - 在程序启动时自动执行代码而不违反 ODR,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62467910/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com