使用reinterpret_cast通过指针地址访问数据的主要目的是什么。是否更快,如果是这样,究竟是怎么回事?
在程序下面,通过打印相同的结构数据。运算符和via指针(重新解释转换)。
#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;
}
答案 0 :(得分:2)
不,不快。 (虽然这取决于你想要做什么)
稍微修改你的例子
char* charPtr = reinterpret_cast<char*>(&v);
说,'让我把这个对象视为一个原始的字节数组'。有很多理由想要这样做。他们中的许多人将通过读,写,发送,memcpy等方式复制内容。
您还可以看到反向
values *v = reinterpret_cast<values*>(buff);
你有一个字节数组,你想把它当作一个结构(你刚读过你之前写过的东西。
请注意,这是一项高级技术,与填充,字节顺序等有很多陷阱。不是100级的事情
答案 1 :(得分:1)
你所拥有的东西是不可靠的,因为当你增加intPtr时,它会通过整数的大小(你告诉它指向的内容)在内存中前进。无法保证结构中的字段是整数大小的。当然,它们不是所有整数大小的项目,并且编译器可以在结构中的字段之间添加填充。增加指针并不会试图找到下一个实际上的位置,它只是指向它所指向的大小。这只适用于数组。
Reinterpret_cast主要告诉编译器让你做一些它知道不好的事情。比如尝试将结构视为数组。除非是你不应该做的事情,否则它不会加快速度。
答案 2 :(得分:1)
您只能通过所谓的指针访问权限访问第一个成员。这是允许的,因为v
和v.one
根据[basic.compound] paragraph 4是指针可互换的:
如果出现以下情况,则两个对象a和b是指针可互换的:
...
一个是标准布局类对象,另一个是该对象的第一个非静态数据成员,或者......
...
如果两个对象是指针可互换的,那么它们具有相同的地址,并且可以通过
reinterpret_cast
从指向另一个的指针获得一个指针。
但是,我能看到的唯一好处是,即使您不知道其名称,也可以访问该成员(例如,您的示例中为one
)。
注意:我相信应该没有性能提升。否则,优化程序可以优化v.one
的评估,就好像reinterpret_cast<int*>(&v)
被评估而不是,因为他们知道它们在编译时是等效的。
在示例中通过指针访问访问其他成员是未定义的行为。正如@TWBennet所说,一个原因是相邻成员之间可能存在填充。但是,即使没有填充,intptr++
也只会获得pointer past-the-end,即使在同一地址也不会自动指向该成员。您可以在that question中查看详细信息。