c++ - 为什么允许将指针转换为引用?

标签 c++ pointers casting reference

原来是this question的话题,发现 OP 只是忽略了取消引用。同时,this answer让我和其他一些人思考 - 为什么允许使用 C 样式强制转换或 reinterpret_cast 将指针强制转换为引用?

int main() {
    char  c  = 'A';
    char* pc = &c;

    char& c1 = (char&)pc;
    char& c2 = reinterpret_cast<char&>(pc);
}

以上代码在 Visual Studio 上编译时没有任何警告或错误(关于类型转换),而 GCC 只会给你一个警告,如图所示 here .


我的第一个想法是指针以某种方式自动被取消引用(我通常使用 MSVC,所以我没有收到 GCC 显示的警告),并尝试了以下操作:

#include <iostream>

int main() {
    char  c  = 'A';
    char* pc = &c;

    char& c1 = (char&)pc;
    std::cout << *pc << "\n";

    c1 = 'B';
    std::cout << *pc << "\n";
}

显示了非常有趣的输出 here .因此,您似乎正在访问指向的变量,但与此同时,您却没有。

想法?解释?标准引号?

最佳答案

嗯,这就是 reinterpret_cast 的目的。 !顾名思义,该转换的目的是将内存区域重新解释为另一种类型的值。因此,使用 reinterpret_cast您始终可以将一种类型的左值转换为另一种类型的引用。

这在语言规范的 5.2.10/10 中有所描述。它还说reinterpret_cast<T&>(x)*reinterpret_cast<T*>(&x) 相同.

在这种情况下,您正在转换 指针 的事实完全不重要。不,指针不会自动取消引用(考虑到 *reinterpret_cast<T*>(&x) 的解释,人们甚至可能会说相反的情况:自动获取该指针的地址)。在这种情况下,指针只是“占用内存中某个区域的某个变量”。该变量的类型没有任何区别。可以是 double ,一个指针,一个 int或任何其他左值。该变量被简单地视为您重新解释为另一种类型的内存区域。

至于 C 风格的类型转换 - 它只是被解释为 reinterpret_cast在这种情况下,因此上述内容立即适用于它。

在您的第二个示例中,您附加了引用 c指针变量pc占用的内存.当你做 c = 'B' ,你强行写入值 'B'进入该内存,从而完全破坏原始指针值(通过覆盖该值的一个字节)。现在被破坏的指针指向一些不可预测的位置。后来你试图取消引用那个被破坏的指针。在这种情况下会发生什么纯属运气问题。程序可能会崩溃,因为指针通常是不可延迟的。或者你可能会很幸运,让你的指针指向一些不可预测但有效的位置。在那种情况下,你的程序会输出一些东西。没有人知道它会输出什么,也没有任何意义。

可以将您的第二个程序重写为等效程序而无需引用

int main(){
    char* pc = new char('A');
    char* c = (char *) &pc;
    std::cout << *pc << "\n";
    *c = 'B';
    std::cout << *pc << "\n";
}

从实际的角度来看,在 little-endian 平台上,您的代码会覆盖指针的最低有效字节。这样的修改不会使指针指向离它原来的位置太远。因此,代码更有可能打印一些东西而不是崩溃。在 big-endian 平台上,您的代码会破坏指针的最高有效字节,从而将其疯狂地抛出以指向完全不同的位置,从而使您的程序更容易崩溃。

关于c++ - 为什么允许将指针转换为引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5924248/

相关文章:

c++ - 覆盖派生类中的模板基方法?

c++ - 是否可以在运行时确定指针指向 C++ 类还是指向 Objective-C 类?

c - 如何复制结构?

vb.net - 测试字符串是否可以在 VB.NET 中转换为整数

c++ - C 多行宏问题 : why not use if(1){. ..} 而不是多行宏定义中的 do{...}while(0)

c++ - WCHAR 到 LPCWSTR

C++ 取消引用字符指针(图像数组)非常慢

c - C中的指针转换代码是什么意思

c - 强制转换时条件表达式中的类型不兼容

c++ - 在 C++ 中转换为 void* 和 typedef