我阅读了Definitions and ODR页面,并且还阅读了有关ODR的几个相关问题。仍然不明白为什么它很重要。
例如,在file1.cpp中:
int val = 2;
在file2.cpp中:
extern int val;
在main.cpp中:
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate *myDate = [df dateFromString:@"2017-06-23 15:34:48"];
NSLog(@"%@", myDate);
此案件违反了ODR。但在实际情况下,有人会这样做吗?我的意思是一个具有相同类型相同名称的变量的定义似乎是自然的。即使有人这样做,编译器或链接器也不会同意。我不明白为什么我们应该关心ODR,因为如果我们编写错误的代码,编译器或链接器将给出错误。是否有可能在未被发现的情况下违反ODR?任何人都可以列出我们经常犯的一些真实案例或错误吗?
答案 0 :(得分:3)
我不明白我们为什么要关心ODR,因为如果我们写错了代码,编译器会给出错误。
ODR是唯一允许编译器发出错误消息的东西。如果我们没有ODR,编制者将被要求接受此类代码。
可以在编译代码时违反ODR吗?
不确定。根据编译器的不同,这可能会编译和链接而不会出现任何问题,或者可能会失败:
extern int var;
int main() {
int myvar = var;
}
请注意此处缺少var
的定义。
有些编译器发现局部变量myvar
完全未使用,因此也删除了对var
的引用。其他编译器/链接器会抱怨缺少var
的定义。而对于其他一些,它取决于您传递的编译器标志。
另一个例子:
// t1.cc
int var;
// t2.cc
long var;
有些编译器会为int var
和long var
提供相同的内部名称并检测冲突,其他编译器会包含类型,并且不会发现任何冲突。
答案 1 :(得分:2)
您可以在翻译单元或匿名名称空间中将此变量声明为static
。
static
全局变量确实具有内部链接,因此不会违反ODR。
file1.cpp
static int val = 1;
// OR
namespace
{
int val = 1;
}
file2.cpp
static int val = 2;
// OR
namespace
{
int val = 2;
}
如果您有两个具有相同全局变量的DLL,并且您在应用程序中加载了两个共享库,那该怎么办?