C++ 11在链接上调用注册函数?

And*_*zos 9 c++ c++11

是否有任何方法可以通过链接其.o文件来调用函数?

例如:

Foo.cpp中:

extern int x;

void f() { x = 42; }

struct T { T() { f(); } } t; // we use constructor of global
                             // object to call f during initialization
Run Code Online (Sandbox Code Playgroud)

bar.cpp:

#include <iostream>

int x;

int main()
{
    std::cout << x;
}
Run Code Online (Sandbox Code Playgroud)

编译/链接/运行:

$ g++ -c foo.cpp
$ g++ -c bar.cpp
$ g++ foo.o bar.o
$ ./a.out
42
Run Code Online (Sandbox Code Playgroud)

这似乎适用于gcc 4.7.它按预期输出42.但是我记得在一些旧的编译器上我遇到了这个模式的问题,因为没有什么真正"使用"foo.o它在链接时被优化了.(也许这个特定的例子由于某种原因不代表问题)

C++ 11标准对这种模式有什么看法?它保证有效吗?

Ker*_* SB 8

我相信你没有摆脱困境.该标准并不保证您的代码按预期工作,尽管许多人依赖该行为进行各种"自我注册"构造.

您的对象t是动态初始化的,具有调用的副作用f.关于静态存储对象的动态初始化(3.6.2/4,"非局部变量的初始化"),标准就是这样说的:

实现定义是否在第一个main语句之前完成具有静态存储持续时间的非局部变量的动态初始化.如果初始化被推迟到第一个main语句之后的某个时间点,则它应该在与要初始化的变量相同的转换单元中定义的任何函数或变量的第一个odr-use(3.2)之前发生.

在您的代码中,仅x使用odr,但x在主翻译单元中定义.其他TU的变量或功能在您的程序中没有使用,因此从技术上讲,无法保证t永远不会被初始化.从技术上讲,每个TU中的某些内容必须由程序的静态控制流引用,以便对所有内容进行初始化.

正如我所说,有很多真实世界的代码带有"自注册"翻译单元(例如在字符串键控映射中注册工厂函数指针),因此只需将TU添加到最终程序即可更多功能.我被告知,大多数编译器都会无条件地初始化所有全局变量,因为不这样做会破坏很多现实世界的代码.但是不要依赖它!

  • @DietmarKühl:没有odr-use,`t`的初始化可以永远推迟,而且`f`永远不会被调用. (2认同)