Gle*_*aum 18 c++ optimization portability pointers
如果有一个类需要一个指针和一个bool.为简单起见,int将在示例中使用指针,但指针类型无关紧要,只要它指向size()大于1的内容即可.
使用{ bool , int *}数据成员定义类将导致类的大小是指针大小的两倍,并浪费大量空间
如果指针未指向char(或其他数据size(1)),那么可能低位将始终为零.该课程可以定义为{int *}或方便:union { int *, uintptr_t }
将bool通过设置/清除指针的低位按照逻辑实现的bool价值和清除该位,当你需要使用指针.
定义的方式:
struct myData
{
int * ptr;
bool flag;
};
myData x;
// initialize
x.ptr = new int;
x.flag = false;
// set flag true
x.flag = true;
// set flag false
x.flag = false;
// use ptr
*(x.ptr)=7;
// change ptr
x = y; // y is another int *
Run Code Online (Sandbox Code Playgroud)
建议的方式:
union tiny
{
int * ptr;
uintptr_t flag;
};
tiny x;
// initialize
x.ptr = new int;
// set flag true
x.flag |= 1;
// set flag false
x.flag &= ~1;
// use ptr
tiny clean=x; // note that clean will likely be optimized out
clean.flag &= ~1; // back to original value as assigned to ptr
*(clean.ptr)=7;
// change ptr
bool flag=x.flag;
x.ptr = y; // y is another int *
x.flag |= flag;
Run Code Online (Sandbox Code Playgroud)
这似乎是未定义的行为,但这有多便携?
Kei*_*son 11
只要在尝试将其用作指针之前恢复指针的低位,只要您的系统,C++实现和代码满足某些假设,它就可能 "合理"可移植.
我不一定能给你一个完整的假设清单,但不是我的头脑:
char,unsigned char,signed char,int8_t,和uint8_t.(并假设CHAR_BIT == 8;在具有16位或32位字节的外来系统上,可能会排除其他类型.)int在一个奇数地址访问一个4字节,但它会稍慢.但编译器通常会安排将对象存储在偶数地址中.其他架构可能有不同的要求.对于最后一个假设,我实际上有一个具体的反例.在Cray矢量系统(J90,T90和SV1是我自己使用过的)上,机器地址指向64位字,但Unicos下的C编译器设置CHAR_BIT == 8.字节指针在软件中实现,其中一个字内的3位字节偏移存储在64位指针的其他未使用的高阶 3位中.因此,指向8字节对齐对象的指针很容易将其低位设置为1.
有Lisp实现(例如使用低位2位指针来存储类型标记.我模糊地回忆起这会导致移植过程中出现严重问题.
一句话:对于大多数系统来说,你可能会放弃它.未来的架构在很大程度上是不可预测的,我可以很容易地想象你的计划打破了下一个Big New Thing.
有些事情需要考虑:
你可以将布尔值存储在类外的位向量中吗?(保持指针与位向量中相应位之间的关联留作练习).
考虑将代码添加到失败并显示错误消息的所有指针操作,如果它看到指针的低位设置为1. #ifdef用于删除生产版本中的检查代码.如果您在某个平台上遇到问题,请在启用检查的情况下构建代码版本并查看会发生什么.
我怀疑,随着应用程序的增长(它们很少收缩),你需要存储的不仅仅是bool指针.如果发生这种情况,空间问题就会消失,因为无论如何你已经在使用那个额外的空间了.
| 归档时间: |
|
| 查看次数: |
3426 次 |
| 最近记录: |