Joã*_*nso 5 c++ one-definition-rule language-lawyer c++11
这基本上是我先前关于DR 712的问题的延续.让我首先解释为什么我坚持要看一些可以被认为是旧的东西,如C++ 11标准,但我的问题是该部分[基本的. def.odr]在C++ 11中已经很难理解了,在我深入研究当前草案中的相同部分之前我想完全覆盖它,在我看来,这个部分更加复杂.
Austing Hasting的前一个问题的答案很好,但我仍然有一点在C++ 11的[basic.def.odr]/2中不明确.考虑这个小而简单的例子:
const int i = 1;
int main()
{
int j = i;
}
Run Code Online (Sandbox Code Playgroud)
从[basic.def.odr]/2在C++ 11 i是未 odr-used在int j = i;作为i是满足用于以恒定表达和左值到右值转换出现被立即应用到要求的对象i.这对我来说没有多大意义,正如i在声明中使用的int j = i;那样,在这里显示的略微修改的代码中可以看出,我强制变量i不被编译的代码优化.
当然,上面的推理肯定有问题,因为我不相信C++ 11在这么简单的例子中可能是错的.再一次,我现在想念的是什么?
我试图将我对"使用过的"标准和"使用的一个定义规则"的理解转化为更直观的东西."使用过的"和"使用ODR"以外的术语不是以下标准定义的术语.
使用ODR的东西基本上意味着"我们需要它来拥有一个身份".这通常意味着有人正在引用它或指向它.
如果您只需要某些东西的价值,这并不总是使其成为ODR使用者.编译时常量的值不需要标识.
在C++中,身份基本上意味着"它实际上必须存储某个地方".
该标准没有说"如果我们需要它具有身份,则使用ODR",因为不同的编译器将有不同的规则来确定他们是否需要身份.例如,如果内联操作并且引用被省略,这是否意味着它不再需要身份?
因此,该标准描述了ODR使用的含义,并将其与所使用的值区分开来.
int j = i;
Run Code Online (Sandbox Code Playgroud)
这不需要身份i.它只需要它的价值. const int i = 1;具有一个不能(在定义的行为下)改变的值.
int const* pj = &i;
Run Code Online (Sandbox Code Playgroud)
这确实需要一个身份.两个不同的指针i必须就i标准下的位置达成一致.
void foo( const int& x ) {
int j = x;
}
foo(i);
Run Code Online (Sandbox Code Playgroud)
这也需要一个身份i.我们参考一下i.尽管我们做的唯一事情就是引用它的价值,但该引用的(简短的,理论上的)存在意味着它具有一种身份.
const int a = 3; const int b = 4;
int i = (a<2)?a:b;
Run Code Online (Sandbox Code Playgroud)
缺陷是有必要a和b有身份(他们使用ODR),因为?与使用规则的相互作用.缺陷是说"我们应该解决这个问题".
在该决议之后,只有该表达式的值a和b所需的值,而不是它们的身份,因此它们不需要存储.
我们关心某些东西是否存储,因为需要存储的东西必须具有独特的定义点.它们基本上不能纯粹存在于头文件中.
请注意,对于C++中的内联变量,我们可能不太关心这一点; 在as-if规则下,如果没有人真正关注身份,则可以删除创建的内联存储位置.由于函数const&可以"意外地"强制标识要求仅仅是有价值令牌的东西,这是一个很好的放松规则.