Use*_*482 6 c++ const-correctness language-lawyer clang++ reference-binding
我有以下代码
#include <iostream>
void foo(const int* const &i_p) {
std::cout << &i_p << std::endl;
}
int main () {
int i = 10;
int* i_p = &i;
std::cout << &i_p << std::endl;
foo(i_p);
}
Run Code Online (Sandbox Code Playgroud)
x86-64 clang 9.0.0输出上是
Program returned: 0
0x7ffc43de63f8
0x7ffc43de6400
Run Code Online (Sandbox Code Playgroud)
x86-64 clang 10.0.0 而在编译器资源管理器链接上,输出变为
Program returned: 0
0x7ffc9da01ef0
0x7ffc9da01ef0
Run Code Online (Sandbox Code Playgroud)
这里进行了什么优化来提供相同的地址?我相信应该实现一个临时对象,因为我们无法将低级const指针绑定到低级non-const。
这里进行了什么优化来提供相同的地址?我相信应该实现一个临时对象,因为我们无法将低级
const指针绑定到低级非const.
没有什么窍门:
int*将 an 转换为是有效的const int*,并且int**为 a是有效的const int * const *int**与const int**此处无关)。请参阅为什么将“指向非 const 的指针的指针”转换为“指向 const 的指针的指针”不合法。
你只有一个i_p指针,自然地,&i_pinmain和&i_pinfoo应该产生相同的地址。
foo接受对指针的引用,因此它应该引用 中的指针main。
const int * const是引用兼容的,int *因为指向 的指针int*, ieint**可以const int * const*通过限定转换转换为。因此,对的引用const int * const可以绑定到int*.
没有什么需要创建第二个对象,至少在当前草案中不需要。
const int&可以绑定到int而不创建单独的对象,并且相同的原则适用于您的情况。
然而,过去并不总是这样,并且在引用绑定期间并不总是考虑限定转换。 CWG2018。限定转换与引用绑定指出,不考虑限定转换并创建临时对象,如下例所示:
Run Code Online (Sandbox Code Playgroud)const int &r1 = make<int&>(); // ok, binds directly const int *const &r2 = make<int*&>(); // weird, binds to a temporary const int *&r3 = make<int*&>(); // error const int &&x1 = make<int&&>(); // ok, binds directly const int *const &&x2 = make<int*&&>(); // weird, binds to a temporary const int *&&x3 = make<int*&&>(); // weird, binds to a temporary
注意:仍然存在一些编译器差异;GCC 认为x3格式不正确,clang 执行临时物化。
这个例子r2正是你的情况。如果const int* const &i_p不是简单地绑定到i_pinmain而是在调用时创建一个全新的临时指针foo,那么它将是一个单独的对象。请注意,const&由于临时物化,可以绑定到临时对象。如果i_pinfoo绑定到一个单独的临时对象,那么它也需要有一个与 in 不同的地址main。
不过,此行为是一个缺陷,已由 CWG2352 修复:相似类型和引用绑定。新的措辞已在 GCC 7 和 clang 10 中实现,这就是为什么您不再看到创建两个单独的指针的原因。