【发布时间】:2011-12-01 23:16:48
【问题描述】:
为什么会这样?
我看到类似的 SO 问题表明确实如此,但有人可以更详细地解释一下吗?特别是,这种行为是否受标准保护?
i.h
#ifndef I_H_
#define I_H_
typedef void (*FuncPtr)();
template<typename T>
void FuncTemplate() {}
class C {};
#endif
a.cc
#include "i.h"
FuncPtr a() {
return &FuncTemplate<C>;
}
b.cc
#include "i.h"
FuncPtr b() {
return &FuncTemplate<C>;
}
m.cc
#include <iostream>
#include "i.h"
FuncPtr a();
FuncPtr b();
int main() {
std::cout << (a() == b() ? "equal" : "not equal") << std::endl;
return 0;
}
然后
$ g++ -c -o a.o a.cc
$ g++ -c -o b.o b.cc
$ g++ -c -o m.o m.cc
$ g++ a.o b.o m.o -o prog
$ ./prog
equal
将-Wall -Wextra -Werror -ansi 扔到所有g++ 调用上会产生相同的结果。
我的(天真的)理解是FuncTemplate 在每个a.o 和b.o 编译单元中被实例化一次,因此地址应该每个都指向一个副本。毕竟这些最终是如何相同的,这种行为是可移植的还是受保护的?
EDIT共享库案例:
$ g++ -shared -o liba.so a.cc
$ g++ -shared -o libb.so b.cc
$ g++ -c -o m.o m.cc
$ g++ -L. -la -lb m.o -o prog
$ ./prog
equal
【问题讨论】:
-
我会在您的问题中添加“当您用共享库替换目标文件时会发生什么?”。
-
你有没有在模板函数或类体中尝试过这个?我不认为这会有所作为,但这肯定是一个有趣的结果。我也很好奇如果你将空类
C移动到a.cc和b.cc会发生什么。我认为它会改变结果。 -
@keith.layne 是的,向
FuncTemplate添加琐碎(但取决于模板参数)代码,或向C添加各种成员不会改变任何东西。至于移动C,#include已经有效地做到了。
标签: c++ function templates linker c++-address