2017-02-16 78 views
2

我很好奇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运算符正确认识从基址指针单独的那个如此释放的4个字节,dbl_var = variant<double>这样释放了8个字节,因此它释放了28个字节。

但它是如何知道的?新操作员是否存储大小为&的指针,然后删除操作员可以使用它来释放正确数量的字节?我知道这是怎么删除[]数组的作品,但我无法找到任何信息,当它来到派生类

+0

这是实现定义的。您需要指定您想要了解哪些实现以获得有意义的答案。 –

+0

总之,是的。堆分配具有已创建的每个对象的大小和类型信息。调用删除将进入查找表并释放给定对象的相应数量的字节。 – callyalater

+2

标准库的'operator new'的默认堆内存分配器“知道”每个分配给您的指针拥有多少内存。它是负责清理的人员,在运行时已经正确地调用适当的析构函数。 – WhiZTiM

回答

8

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

确定分配大小与分配内存的类型无关。运营商deletedelete[]甚至不知道要删除的指针的类型,因为它们在void指针上运行。

+0

清除了我的疑惑,谢谢。 – Budskii

相关问题