我正在努力理解为什么以下代码中第二个 assert 失败(如果有关系的话,是在 Visual Studio 2019 中使用 MSVC):
据我所知,对于多态类型的指针,
因此我的问题如下:
1.
在搜索并尝试自我学习时,我在有关虚表的一系列博客文章中发现了以下内容:https://shaharmike.com/cpp/vtable-part4/。在博客文章中有一个简短的关于析构函数的片段提到:
“这里是一个快速的思考练习:为什么析构函数会将 vtable 指针更改为指向自己的类,而不是保持指向具体类?答案:因为在析构函数运行时,任何继承类都已经被销毁了。不希望调用这些类的方法。”
从这里,我猜想
#include <cstdlib>
class grandparent
{
public:
virtual ~grandparent() {};
};
class parent : public virtual grandparent
{};
class child : public parent
{};
int main()
{
void* mem = malloc(sizeof(child));
child* c = new (mem) child;
assert(dynamic_cast<void*>(c) == mem); // ok
std::destroy_at(c);
assert(dynamic_cast<void*>(c) == mem); // fails
}
据我所知,对于多态类型的指针,
dynamic_cast<void*>
将返回该指针最终派生类的地址。在通过 std::destroy_at
进行销毁之前,这个过程完全正常。但是,在销毁后它不再提供指向最初分配的内存的指针,但我不明白为什么会这样。因此我的问题如下:
1.
dynamic_cast<void*>
如何获取给定指针的最终派生类型的地址?
2. 析构函数做了什么使得它更改了 dynamic_cast<void*>
的返回值?在搜索并尝试自我学习时,我在有关虚表的一系列博客文章中发现了以下内容:https://shaharmike.com/cpp/vtable-part4/。在博客文章中有一个简短的关于析构函数的片段提到:
“这里是一个快速的思考练习:为什么析构函数会将 vtable 指针更改为指向自己的类,而不是保持指向具体类?答案:因为在析构函数运行时,任何继承类都已经被销毁了。不希望调用这些类的方法。”
从这里,我猜想
dynamic_cast<void*>
的工作方式是通过查看给定指针的虚表,就像引用的那句话一样,当调用析构函数时更改了虚表指针。这个猜测正确吗?如果是,我想了解底层发生了什么,因此任何解释或进一步阅读资料将不胜感激。
std::destroy_at
后使用dynamic_cast<void*>(c)
会导致未定义行为。 - R Sahustd::destroy_at(c)
做什么方面。 - smac89mem
,一旦完成所有操作就可以释放它。 - NathanOliver