在以下类型的代码中从指针转换为 ref 是否有任何成本?
void bar(Obj&);
void foo(Obj* o) {
bar(*o);
}
一方面,指针的值是
Obj
的地址,因此编译器可以将该值重新解释为引用。然而,如果 o
是一个空指针,那么该 deref 就会崩溃,因此,大概那里有一个内存读取。编译器没有关于指针是否有效的上下文。
我知道在某些情况下,当编译器在转换附近有足够的上下文时,它可以省略转换的读取。
我发现了另一个问题,但该答案适用于不同的场景:将指向向量的指针转换为引用的成本
实际上,此操作没有任何成本。 为了可视化这一点,您可以在启用优化的情况下编译以下代码:
struct Obj;
void bar(Obj&);
void foo(Obj* o) {
bar(*o);
}
GCC 将其编译为:
foo(Obj*):
jmp bar(Obj&)
在 ABI 级别,指针和引用都作为它们所引用的对象的内存地址进行传递,因此它们可以互换,无需任何操作。
但是,如果
是o
,那么该 deref 就会崩溃,因此,据推测,那里读取了内存。nullptr
不,这不一定会发生。 如果
o
是空指针,则取消引用它是未定义的行为。
这并不意味着程序必须崩溃;而是意味着程序必须崩溃。这只是意味着在这种情况下任何事情都可能发生。
在这种情况下,它会导致引用绑定到不是实际对象的东西,这是不可能的。这可能会进一步破坏一些代码。
我知道,在某些情况下,当编译器在转换附近有足够的上下文时,它可以省略转换的读取。
此代码中既没有读取也没有转换,至少在 C++ 标准意义上是这样。 取消引用指针不会从所指向的对象中读取,并且绑定引用不被视为转换。