【问题标题】:How does delete know the size of derived class from base pointer?delete 如何从基指针知道派生类的大小?
【发布时间】:2017-07-06 03:52:40
【问题描述】:

我很好奇 delete 操作符在基指针上调用 delete 时如何知道派生类的大小,这是一个最小的例子:

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());
    }
};

测试:

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;
}

delete 运算符仅从基指针就正确地知道 int_var = variant&lt;int&gt; 所以释放了 4 个字节,dbl_var = variant&lt;double&gt; 所以释放了 8 个字节,str_var = variant&lt;std::string&gt; 所以它释放了 28 个字节。

但它怎么知道呢? new 运算符是否存储大小和指针,然后删除运算符可以使用它来释放正确的字节数?我知道这就是 delete[] 对数组起作用的方式,但是在派生类方面我找不到任何信息

【问题讨论】:

  • 这是实现定义的。您需要指定您想了解的实现以获得有意义的答案。
  • 简而言之,是的。堆分配具有已创建的每个对象的大小和类型信息。调用 delete 将转到查找表并释放给定对象的相应字节数。
  • 标准库operator new 的默认堆内存分配器“知道”它分配给您的每个指针拥有多少内存。它负责清理,原因是运行时正确调用了适当的析构函数。
  • @callyalater "大小和类型信息" - 堆分配器有哪些类型信息?
  • @NirFriedman 在 typedef、using 或成员变量上下文中使用时,某些实现将存储模板类型大小(我的意思是类型信息)以确定要使用的偏移量并提供类型检查在运行时。但是,类型信息(如果有)是实现定义的。

标签: c++


【解决方案1】:

deletedelete[] 运算符知道分配的大小,因为运算符newnew[] 在分配时为它们保存了一些内务信息。当malloc 保存free 完成其工作所需的大小信息时,它使用与malloc/free 对相同的想法。

确定分配大小与分配内存的类型无关。运算符deletedelete[] 甚至不知道要删除的指针的类型,因为它们操作的是void 指针。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-28
    • 2020-03-04
    • 2020-07-23
    相关资源
    最近更新 更多