C++存储重用未定义行为:析构问题及std::launder作用问询
问题解答
1. 为何h()函数作用域结束时会导致未定义行为?
先看代码中的关键场景:
void h() { B b; // 自动存储期的非平凡可析构对象 b.~B(); // 显式结束B对象的生存期 new (&b) T; // 在原内存构造不同类型的T对象 } // 作用域结束,触发隐式析构
根据C++对象生存期规则:
若程序显式结束一个作为变量的非平凡可析构对象的生存期,必须确保在隐式调用析构函数前,在原内存位置构造一个同类型的新对象;否则行为未定义。
核心原因在于:编译器会将b识别为B类型的自动变量,在作用域结束时无条件生成调用B::~B()的代码。但此时b的内存中实际存储的是T类型对象,对非B类型的对象调用B的析构函数属于类型不匹配的非法操作,直接触发未定义行为。
2. 使用std::launder能否解决该未定义行为问题?
不能。
std::launder的作用是告知编译器:某块内存已经构造了新对象,需要绕过原对象的生存期限制来访问新对象。但它无法改变编译器对自动变量的隐式析构逻辑——编译器仍会在h()作用域结束时,为变量b生成调用B::~B()的代码,不管当前内存中实际存储的是T对象。
即便通过std::launder获取了T对象的合法引用或指针,作用域结束时的隐式B::~B()调用依然会触发类型不匹配的非法操作,未定义行为无法消除。
内容的提问来源于stack exchange,提问作者getsoubl
相关产品推荐
相关产品推荐

