基础和派生类分配

时间:2013-03-21 16:07:01

标签: c++

在下面的代码中,drvdCls来自bseCls。此代码按原样编译和运行。但是我在这里发现了一个问题:newBse退出Test()后会被取消分配。我是对的吗?

bseCls* Test()
{

    bseCls* newBse = new drvdCls();
    drvdCls newDrvd;
    newBse = &newDrvd;
    return newBse;

}

3 个答案:

答案 0 :(得分:4)

newBse最初指向的对象将被泄露。当您将newDrvd的地址分配给newBse时,您将丢失指向堆分配对象的指针,并且您将无法delete它。在进程终止之前,此内存将无法使用。

此外,您将堆栈分配的对象的地址作为指针返回,这有两个原因:

  1. 在函数返回之前,将调用对象的析构函数,这意味着您将使用指向被破坏对象的指针。
  2. 为对象分配的内存存在于堆栈中,几乎肯定会受到未来函数调用的破坏。此时,您的指针将指向不是bseCls的内容,但您将像使用它一样使用它。
  3. 如果您使用此函数返回的指针,则表示您正在调用未定义的行为,并且您的程序具有执行任何的许可。

答案 1 :(得分:1)

不,它不会自动解除分配。必须通过拨打new来匹配对delete的每次通话。但这不是你的代码唯一的问题,你也从函数返回局部变量的地址。

newBse = &newDrvd; // memory leak, pointer to previously allocated object is lost
return newBse;     // newDrvd is destroyed when function exits, so returned
                   // pointer points to invalid memory

您可能想要做的是

bseCls* Test()
{
    return new drvdCls();
}

现在调用者在使用后必须在返回的指针上调用delete。你应该做的是

std::unique_ptr<bseCls> Test()
{
    return new drvdCls();
}

现在,当返回的delete超出范围时,分配的对象将自动为unique_ptr

答案 2 :(得分:0)

您有两个危险的缺陷

  • drvdCls newDrvd;在堆栈上声明一个本地对象,从函数返回后,它将被销毁。然后,指向newBse的{​​{1}}将无效。

  • newDrvd分配给&newDrvd后内存泄漏。

让我们仔细看看:

newBse