类型双关
类型双关就是在同样的一个内存中,存储的数据可以用做不同类型的表述。用在底层性能优化的时候,一般使用的时候要非常小心,因为不当的使用可能导致程序的不稳定和不可预测的行为。
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();
修改成功!想法正确!