通过指针访问数据(重新解释转换)与 .或 -> 运算符
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 主要是告诉编译器让你做一些它知道是个坏主意的事情。例如试图将结构视为数组。它不会加快任何速度,除非这是你不应该做的事情。
您只能通过所谓的指针访问来访问第一个成员。这是允许的,因为 v
和 v.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 .
使用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 主要是告诉编译器让你做一些它知道是个坏主意的事情。例如试图将结构视为数组。它不会加快任何速度,除非这是你不应该做的事情。
您只能通过所谓的指针访问来访问第一个成员。这是允许的,因为 v
和 v.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