C++ delete如何从基指针知道派生类的大小?
我很好奇,当对基指针调用delete时,delete操作符如何知道派生类的大小,下面是一个简单的示例:C++ delete如何从基指针知道派生类的大小?,c++,C++,我很好奇,当对基指针调用delete时,delete操作符如何知道派生类的大小,下面是一个简单的示例: class IVariant { public: virtual ~IVariant() = default; virtual void print_value() = 0; }; template<typename T> class Variant: public IVariant {}; template<> class Variant<i
class IVariant
{
public:
virtual ~IVariant() = default;
virtual void print_value() = 0;
};
template<typename T>
class Variant: public IVariant {};
template<>
class Variant<int>: public IVariant
{
private:
int m_integer;
public:
Variant(int integer): m_integer(integer) {}
void print_value() override
{
printf("integer: %i\n", m_integer);
}
};
template<>
class Variant<double>: public IVariant
{
private:
double m_dbl;
public:
Variant(double val): m_dbl(val) {}
void print_value() override
{
printf("double: %g\n", m_dbl);
}
};
template<>
class Variant<std::string>: public IVariant
{
private:
std::string m_string;
public:
Variant(const std::string& string): m_string(string) {}
void print_value() override
{
printf("string: %s\n", m_string.c_str());
}
};
类变量
{
公众:
virtual~IVariant()=默认值;
虚空打印_值()=0;
};
模板
类变量:公共变量{};
模板
类变量:公共变量
{
私人:
整数;
公众:
变量(整数):m_整数(整数){}
无效打印值()覆盖
{
printf(“整数:%i\n”,m_整数);
}
};
模板
类变量:公共变量
{
私人:
双m_-dbl;
公众:
变体(双val):m_dbl(val){}
无效打印值()覆盖
{
printf(“双精度:%g\n”,m_dbl);
}
};
模板
类变量:公共变量
{
私人:
std::string m_string;
公众:
变量(const std::string&string):m_string(string){}
无效打印值()覆盖
{
printf(“字符串:%s\n”,m_string.c_str());
}
};
测试:
intmain()
{
IVariant*int_var=新变量(100);
IVariant*dbl_var=新变异体(100.0f);
IVariant*str_var=新变量(“值为100\n”);
int_var->print_value();
dbl_var->print_value();
str_var->print_value();
删除int_var;
删除dbl_变量;
删除str_var;
}
delete操作符仅从基指针就正确地知道,int\u var=variant
so释放了4个字节,dbl\u var=variant
so释放了8个字节,str\u var=variant
因此释放了28个字节
但它怎么知道呢?新操作符是否存储删除操作符可以用来释放正确字节数的大小和指针?我知道delete[]对数组的作用是这样的,但对于派生类
delete
和delete[]
操作符知道分配的大小,因为操作符new
和new[]
在分配时为它们保存一些内务管理信息。当malloc
保存free
执行其工作所需的尺寸信息时,它使用与malloc
/free
配对相同的思想
计算分配大小与分配内存的类型无关。操作员
delete
和delete[]
甚至不知道要删除的指针的类型,因为他们操作void
指针。这是实现定义的。为了得到有意义的答案,您需要指定您想要了解的实现。简言之,是的。堆分配具有已创建的每个对象的大小和类型信息。调用delete将转到查找表并释放给定对象的相应字节数。标准库的操作符new
的默认堆内存分配器“知道”它分发给您的每个指针拥有多少内存。它负责清理,当然是在运行时正确调用了相应的析构函数之后。@callyalater“大小和类型信息”-堆分配器有什么类型信息?@NirFriedman一些实现在typedef中使用时,会使用,或成员变量上下文,以确定要使用的偏移量,并在运行时提供类型检查。但是,类型信息(如果有)是由实现定义的。
int main()
{
IVariant* int_var = new Variant<int>(100);
IVariant* dbl_var = new Variant<double>(100.0f);
IVariant* str_var = new Variant<std::string>("the value is 100\n");
int_var->print_value();
dbl_var->print_value();
str_var->print_value();
delete int_var;
delete dbl_var;
delete str_var;
}