Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/google-sheets/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;11在链路上调用寄存器函数?_C++_C++11 - Fatal编程技术网

C++ C++;11在链路上调用寄存器函数?

C++ C++;11在链路上调用寄存器函数?,c++,c++11,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 bar.cpp: #include <iostream> int x; i

有没有办法通过链接函数的.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
bar.cpp:

#include <iostream>

int x;

int main()
{
    std::cout << x;
}
这似乎适用于GCC4.7。它按预期产出42项。然而,我记得在一些旧的编译器上,我对这种模式有一个问题,因为没有任何东西真正“使用”foo.o,它在链接时被优化了。(也许由于某种原因,这个特定的例子不能代表这个问题)


关于这个模式,C++11标准有什么说法?是否保证有效?

相关章节为2.2[法律阶段]第1段第8项和第9项:

.8。翻译单元和实例化单元的组合如下:[注:部分或全部可从库中提供。-结束注]检查每个翻译单元以生成所需实例化的列表。[注:这可能包括明确要求的实例化(14.7.2)。-结束注]所需模板的定义位于。是否需要提供包含这些定义的翻译单元的源是由实现定义的。[注:实现可以将足够的信息编码到翻译单元中,以确保此处不需要源代码。-结束注]执行所有必需的实例化以生成实例化单元。[注:这些类似于已翻译的翻译单元,但不包含对未实例化模板的引用,也不包含模板定义。-结束注]如果任何实例化失败,则程序格式错误

.9。解析所有外部实体引用。库组件被链接以满足对当前转换中未定义的实体的外部引用。所有这些转换器输出都被收集到一个程序映像中,该映像包含在其执行环境中执行所需的信息


第8项是我能找到的最好的一项,表明所有翻译单元都必须包括在内。第9项只是说明解析符号所需的一切也都被拉入。实际上,这意味着显式包含翻译单元具有预期效果。但是,将翻译单元放入库中并不能实现这一点。我想这就是你过去的经历:例如,将实现放入库中,并希望它们在启动时注册。由于相应的翻译单元中没有符号解析未引用的符号,因此库中的对象文件不会被拉入,相应地,全局对象也不会被初始化。

我相信您还没有脱离困境。该标准并不保证您的代码按预期工作,尽管许多人依赖于这种行为进行各种“自注册”构造

对象
t
是动态初始化的,其副作用是调用
f
。本标准对静态存储对象的动态初始化(3.6.2/4,“非局部变量的初始化”)作了如下说明:

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

在您的代码中,仅使用了
x
,但在主翻译单元中定义了
x
。您的程序中没有使用来自另一个TU的变量或函数odr,因此技术上无法保证
t
将被初始化。从技术上讲,为了初始化所有内容,程序的静态控制流必须引用来自每个TU的内容


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

该标准并没有真正说明如何选择翻译单元来组合成一个完整的程序,而且据我所知,在C++98和C++11之间,这方面没有什么重要的变化


实际上,当您将TU链接为
.o
时,无论发生什么,您都会得到它的静态初始值设定项,而如果您将它链接为
.a
的一部分,则只有当TU中的其他内容从
main()
或链接为
.o
的另一个文件中被传递引用时,您才会得到它的静态初始值设定项
ld
--整个存档
标志覆盖此项,并将存档的每个成员拉入,就像您将其作为单个
.o
列出一样。其他链接器可能会以不同的方式处理此问题。

我认为这仍然是正确的:标准不要求在调用其翻译单元中的函数之前初始化
t
。这是很难解释的,因此大多数编译器都会按照您的期望进行编译,但您需要知道的是,在这方面您没有标准的支持…@KerrekSB:标准中使用的术语是什么?或者标准的哪一部分解决了这个问题?@KerrekSB:你应该把你的评论作为一个答案,它值得投票对象不必使用odr:quote部分中的odr规则是对实现的限制,而不是对用户的限制。此外,本节讨论初始化顺序,而不是是否包括翻译单元及其局部变量。@DietmarKühl:如果不使用odr,则初始化
t
$ g++ -c foo.cpp
$ g++ -c bar.cpp
$ g++ foo.o bar.o
$ ./a.out
42