类型双关
类型双关就是在同样的一个内存中,存储的数据可以用做不同类型的表述。用在底层性能优化的时候,一般使用的时候要非常小心,因为不当的使用可能导致程序的不稳定和不可预测的行为。
int a = 5;
//double value = (double)a;
double value = *(double*)&a;//会读取到不该读取的内容
//value = 0.0;
std::cout << value;
std::cin.get();
在上述行为的情况下,在大多数编译器和系统会出现未定义行为,因为整数和浮点数的内存布局是不同的,但在修改了value后,上述的a出的内存,因为本质上是一片内存。
struct Entity {
int x, y;
int* getPosition() {
return &x;
/* int* w = new int();
w[0] = x;
w[1] = y;
return w;*/
}
};
上述操作中,声明数组指针返回数组指针和声明int类型指针本质是否是一样的?
重新写了代码,运行结果都是一样的,但是含义不同:
delete w和delete[] w在释放内存中是不同的。
并且使用int指针声明,变量值会默认为0,自动初始化,而声明数组的话,需要完成手动初始化。
int main() {
Entity x{1,2};
int* y = (int*)&x;
std::cout << y[0] << "-" << y[1] << std::endl;
int z = *(int*)((char*)&x + 4);
std::cout << z;
int* u = (int*)((char*)&x + 4);
std::cout << u[-1];
std::cin.get();
}
上述代码中输出如下:
因为char指针占1个字节,所以挪动4次后会位于2的位置,此时转为int指针类型,就指向Entity对象的y。
联合体
联合体就是两种类型同用一篇内存地址,关键字为union。
在部分情况下,可以代替类型双关使用:
struct vector2{
float x, y;
};
struct vector4 {
union {
struct {
float a, b, c, d;
};
struct {
vector2 x, y;
};
};
float a, b, c, d;
vector2& getvector2() {
return *(vector2*)&x;
}
};
在这里对联合体和类型双关的表述是类似的。复习了一下符号重载的运用:
std::ostream& operator<<(std::ostream& stream ,const vector2& other) {
stream << other.x << "," << other.y;
return stream;
}
下面验证一下在联合体中修改联合体的内容:
int main() {
vector4 test = {1.0f, 2.0f, 3.0f, 4.0f};
std::cout << test.x << "-" << test.y << std::endl;
test.c = 50.0f;
std::cout << test.x << "-" << test.y << std::endl;
std::cin.get();
}
输出显示联合体会修改对应的内存信息导致其他成员变量内容改变!!!
下面验证一下在类型双关中:
vector4 test = {1.0f, 2.0f, 3.0f, 4.0f};
std::cout << test.getvector2() << "-" << *(&test.getvector2() + 1) << std::endl;
test.c = 50.0f;
std::cout << test.getvector2() << "-" << *(&test.getvector2() + 1) << std::endl;
std::cin.get();
修改成功!想法正确!