delete 运算符如何使用指向基 class 的指针释放内存

How is memory deallocated by delete operator with pointer to base class

考虑这段代码:

class base{
    T* obj=new T[40];
    //...
public:
    base(){/*...*/}
    virtual ~base(){
        delete[] obj;
        //...
    }
    ...
};
class derived : public base{
    T* obj2=new T[20];
    //...
public:
    derived(){/*...*/}
    ~derived(){
        delete[] obj2;
        //...
    }
    ...
};

void func(){
    base&& exmp=giveder();    //giveder() returns derived
    base* dis=new derived[50];
    //...
    delete[] dis;
}

在上面的代码中,exmp 将被正确地析构,因为析构函数被声明为虚拟的。但我的问题是 dis 指向的免费商店是否会按预期解除分配,如果是,那么如何解除分配?

很明显sizeof(base)sizeof(derived)是不一样的。但这不会与 exmp 混淆,但它会与 dis 混淆吗?我认为它不会工作,因为无法从指向基的指针找出 sizeof(derived) ,因此它无法计算出需要释放多少字节。虽然我真的很想知道语言规范以及它是否合法。如果那是合法的,释放收购中的内容的解决方法是什么?

附带问题,数组不知道自己的大小(对吗?),那么析构函数中的 delete[] objdelete[] obj2 又是如何释放内存的呢?

我是指针和内存管理的新手,所以我更喜欢描述性的答案。谢谢

您的代码有未定义的行为。

可以用

base* ptr = new derived();
delete ptr;

但是用起来不行

base* ptr = new derived[10];
delete [] ptr;

这是相关文本 from the C++11 Standard(强调我的):

In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.

正如其他人已经注意到的,这:

base* dis=new derived[50];
delete[] dis;

未定义的行为。阅读,例如,这个问题来理解为什么:Why is it undefined behavior to delete[] an array of derived objects via a base pointer?.

作为解决方案,我建议使用 唯一指针向量:

struct Base { virtual ~Base() = default; };
struct Derived : Base {
  Derived() { std::cout << "Derived constructed...\n"; }
  ~Derived() { std::cout << "Derived destroyed...\n"; }
};

int main() {
  std::vector<std::unique_ptr<Base>> v;
  std::generate_n(std::back_inserter(v), 50,
                  []{ return std::make_unique<Derived>(); });
}

现场演示:https://wandbox.org/permlink/jcG71bDb1U7wsp2T

当然,在这种情况下,Derived个对象不会被放置在连续的内存块中。