通过指针访问数据(重新解释转换)与 .或 -> 运算符

Accessing data via pointer(reinterpret cast) vs . or -> operator

使用reinterpret_cast通过指针地址访问数据的主要目的是什么。它是否更快,如果是,具体如何?

下面是一个程序,它通过 打印相同的结构数据。运算符和通过指针(重新解释转换)。

#include <iostream>
using namespace std;

struct values{
    int one;
    int two;
    char three;
    int four;
};

int main()
{
    values v { 8, 5, 'k', 653};

    // access via . (or ->) operator
    cout << v.one << endl;
    cout << v.two << endl;
    cout << v.three << endl;
    cout << v.four << endl;


    //via pointer access - how can this be beneficial?
    values* vPtr = &v;
    int* intPtr = reinterpret_cast<int*>(vPtr);
    cout << *intPtr << endl;
    intPtr++;
    cout << *intPtr << endl;
    intPtr++;
    char* charPtr = reinterpret_cast<char*>(intPtr);
    cout << *charPtr << endl;
    charPtr += 4;
    int* intPtr2 = reinterpret_cast<int*>(charPtr);
    cout << *intPtr2<< endl;

    return 0;
}

不,它并不更快。 (虽然这完全取决于你想做什么)

稍微修改一下您的示例

char* charPtr = reinterpret_cast<char*>(&v);

说,'Let me treat this object as a raw array of bytes'。想要这样做的原因有很多。其中许多将与通过读取、写入、发送、memcpy 等方式复制内容有关。

你也可以看到倒数

values *v = reinterpret_cast<values*>(buff);

你有一个字节数组,你想把它当作一个结构(你刚刚读了你以前写的东西。

请注意,这是一项高级技术,在填充、字节顺序等方面存在许多缺陷。不是 100 级的东西

你所拥有的并不可靠,因为当你增加 intPtr 时,它会在内存中前进一个整数的大小(这就是你告诉它指向的)。不能保证结构中的字段是整数大小的。当然,它们并不都是整数大小的项目,编译器可以自由地在结构中的字段之间添加填充。增加一个指针并不会试图找到下一个东西的实际位置,它只是根据它所指向的大小。仅适用于数组。

Reinterpret_cast 主要是告诉编译器让你做一些它知道是个坏主意的事情。例如试图将结构视为数组。它不会加快任何速度,除非这是你不应该做的事情。

您只能通过所谓的指针访问来访问第一个成员。这是允许的,因为 vv.one 根据 [basic.compound] paragraph 4:

是指针可相互转换的

Two objects a and b are pointer-interconvertible if:

  • ...

  • one is a standard-layout class object and the other is the first non-static data member of that object, or, ...

  • ...

If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via a reinterpret_­cast.

但是,我能看到的唯一好处是,即使您不知道其名称(即您的示例中的 one),您也可以访问该成员。

注意:我相信应该没有性能提升。否则,优化器可以优化 v.one 的评估,就好像 reinterpret_cast<int*>(&v) 被评估而不是 知道它们在编译时是等价的 .


在您的示例中通过指针访问来访问其他成员是未定义的行为。正如@TWBennet 所说,原因之一是相邻成员之间可能存在填充。但是,即使没有padding,intptr++也只是得到了一个pointer past-the-end, which will not automatically point to the member even at the same address. You can see details in .