当我们开始覆盖内存时,对象的生命周期是否已经结束?
When we're starting to overwrite memory has lifetime of an object has ended yet?
我无法独自解决以下问题:
假设我们以以下方式重用内存:
struct A
{
int a;
A(){ }
~A(){ }
};
struct B : A
{
int b;
B(){ }
~B(){ }
};
A *a = (A*) malloc(sizeof(A) + sizeof(B));
B *b = new (a) B; //Constructor of B is calling
a
引用的对象的生存期在B
的构造函数开始调用之前已经结束,还是在B
的构造函数完成时已经结束?
您尝试使用placement-new运算符来初始化b
。此运算符不首先调用类A
的析构函数(a
),而是将一个新的析构因子初始化到a
指向的内存中。这是有问题的(如注释中所述),因为sizeof(B)
大于sizeof(A)
,并且在指针a
处只分配了sizeof(A)
。所以这是未定义的行为。
对象CCD_ 12的生存期不会正式结束。你会得到这样的东西:
class A { int a; };
void* p = malloc(sizeof(A));
A* a1 = new (p) A();
A* a2 = new (p) A();
我认为,在同一个内存上会得到类似double的析构函数,但这是编译器实现特定的。我不认为,标准确实说明了这一点。
一旦输入B
的构造函数,a
就不再指向对象A
。
原因是,甚至在对象的构造函数的第一条指令之前,运行时就已经完成了VMT、基本子对象和成员初始化。
此外,如果B
的构造函数没有因为异常而终止,那么内存已经被使用,并且最终出现在同一内存地址的另一个对象不再存在。
换句话说,就是不要那样做。。。在C++中,对象不仅仅是一堆字节,而且它们有权限;例如调用其析构函数的权利;-)
相关章节(3.8)中的标准规定,
T类型对象的寿命在以下情况下结束:
-如果T是具有非平凡析构函数(12.4)的类类型,则析构函数调用启动,或者
-对象占用的存储器被重新使用或释放。
我的意思是,当B
的成员初始化时,a
指向的对象的生命周期结束。在此之前,存储不会被重复使用。
当您删除它时,而不是之前,它的生存期就结束了-因为以这种方式强迫两个不同的对象占用相同的空间本身就是未定义的行为,绝对不建议您的编译器可能会也可能不会将该内存视为可重用并覆盖b。
如果您需要两个对象占据相同的位置,例如:Message Variants,或者您正在尝试编写自己的调试器,那么您应该使用union
类型。
不建议你做这种事情的另一个原因是,你会制造一场维护噩梦。例如,在代码的后面,您可能会有:
b.b = 3
while (a.a > 0) {
b.b--;
}
- 在提升multi_index容器中,是否定义了"default index"?
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 检查输入是否不是整数或数字
- 是否可以初始化不可复制类型的成员变量(或基类)
- 是否可以通过使用移动/交换 c++11 来延长返回的临时变量的生命周期
- 在C++的松弛记忆模型中是否存在具有依赖周期的非因果行为
- 确定邻接矩阵是否具有周期,然后输出该周期
- 就时间复杂度而言,在另一个字符串中找到最小周期字符串是否可以更快
- 是否有一种模式来描述哪个对象控制另一个对象的生命周期?
- xvalue 的生命周期绑定到引用是否延长?
- 当我们开始覆盖内存时,对象的生命周期是否已经结束?
- 是否strand和io对象(如tcp::socket)需要担心相关联的io_service的生命周期?
- 是否有调试机制、解决方法、包装器或工具来检测shared_ptr周期
- 类型转换是否消耗额外的CPU周期?
- 是否有可能保存当前的视口,然后在OpenGL和c++中在下一个绘制周期中重新绘制保存的视口?
- 松弛的内存顺序效果是否可以扩展到执行线程的生命周期之后?
- 临时 B() 是否通过初始化下面的引用 int&ri 来延长其生命周期?
- 在我的代码中,scoped_ptr指向一个堆栈变量 - 这是否延长了堆栈变量的生命周期
- 标准C++11是否保证high_resolution_clock测量实时性(非CPU周期)
- 如果unique_lock在其生命周期内不会再次使用,是否应该在解锁后释放?