c ++中不允许指向整数文字的指针。 但是,我可以使用address-of(&)运算符来获取文字的地址。
const int & a = 5;
const int & b = 5;
cout << &a << endl;
cout << &b << endl;
结果是&amp; a和&amp; b不同!!! 为什么???在字符串文字的情况下,一个字符串文字只有一个内存地址。为什么同一个整数文字在再次声明时会有不同的内存地址?
答案 0 :(得分:4)
你没有获取文字的地址:'5'是一个prvalue,用于初始化int的临时类型,其生命周期绑定到const引用a。所以ansible-playbook
必须(*)保持为真,据我所知:
除非对象是零字段或零大小的基类子对象,否则该对象的地址是它占用的第一个字节的地址。如果一个是另一个的子对象,或者如果至少一个是零大小的基类子对象并且它们具有不同类型,则两个不是位字段的对象可以具有相同的地址;否则,他们将拥有不同的地址 ^ 4。 4 [(*) 在“as-if”规则下,允许实现在同一机器地址存储两个对象或不存储 如果程序无法观察差异]
,则该对象完全没有
此外,作为的演示,如规则,程序
&a!=&b
编译为(gcc 7.2 -O3):
int main(){
const int a = 5;
const int b = 5;
return &b!=&a;
}
:)
答案 1 :(得分:0)
如果右值被引用,则不再是右值。参考一个右值使它被存储就好像它是一个左值。
例如
while (!find || open.Count > 0)
{
Vector2 current = LowestF(Start, open, Destination);
if (current == Destination)
{
find = true;
break;
}
close.Add(current);
open.Remove(current);
List<Vector2> adjacent = MoveDirection(current);
lowF = int.MaxValue;
for (int i = 0; i < adjacent.Count; i++)
{
if (close.Contains(adjacent[i]))
continue;
if(getF(Start, adjacent[i], Destination) < lowF)
{
lowF = getF(Start, adjacent[i], Destination);
lowV = adjacent[i];
}
if (!open.Contains(adjacent[i]))
{
open.Add(adjacent[i]);
}
yield return new WaitForSeconds(0.0125f);
}
}
所以你肯定可以拿一个左值的地址。
答案 2 :(得分:0)
两个文字确实具有相同的地址,该地址是 no-address 。除字符串文字外,文字没有地址。
在您的代码中,您不获取文字的地址,这根本不可能。 address-of运算符需要左值,而文字不是一个!因此,如果您确实尝试使用int* a = &5;
中的文字地址,编译器就不会让您。
您正在创建对rvalue(实际为prvalue)的const
引用。现在,如果您尝试在没有const
关键字的情况下进行编译,并想知道为什么不起作用,那也是出于同样的原因。如果没有constness,则需要左值来绑定引用,而文字不是一个。
注5.1.1:
文字[expr.prim.literal] 文字是主要表达方式。它的类型取决于它的形式(2.13)。字符串文字是左值;所有其他文字都是prvalues。
这就解释了为什么它对字符串文字“起作用”,它们是左值。您可以获取左值的地址。它还解释了为什么它不适用于整数文字。
但请注意,取两个相同的字符串文字的地址不一定会产生相同的地址。你错了。
在优化版本中,或在明确请求时,许多编译器将执行string pooling。非常非常严格地说,从逻辑的角度看这是不正确的(因为两个字符串文字,无论是否相同,是两个不同的对象,除了位域和嵌套对象,不同的对象预计会有不同的地址),但令人惊讶的是,该标准确实允许实施完全合法地摆脱这种情况。
C ++ 98和C ++ 03中的2.13.4 / 2,C ++ 11中的2.14.12 / 11,C ++ 14中的2.14.5 / 12:
是否所有字符串文字都是不同的(即存储在非重叠对象中)是实现定义的。
每个2.13.5 / 16 in C ++ 17:
[...]是否所有字符串文字都是不同的(即存储在非重叠对象中)以及字符串文字的连续评估是否产生相同或不同的对象未指定。
因此,在C ++ 17之前的版本中,编译器(“实现”)可能会选择执行池化,但在“实现定义”的约束下,这意味着特定的编译器必须遵循任何它选择了,发生的事情必须是可证实的(记录在案)。
在C ++ 17中,标准仅表明它未指定。这基本上意味着......“无论如何”。
因此,编译器可以进行字符串池化(合法地),但 的一般假设是错误的。