2013-03-21 129 views
0

在下面的代码中,drvdCls派生自bseCls。此代码编译并按原样运行。然而,我在这里发现一个问题:在Test()退出后,newBse将被释放。我对吗?基础和派生类分配

bseCls* Test() 
{ 

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

} 
+0

不,它不会。这是动态内存分配的重点。但是,在代码中存在严重的问题 - 您将指针指向已分配的内存,并返回一个指向自动变量的指针(在func退出时将释放此指针,最终将解决函数调用器中释放的内存)。 – SomeWittyUsername 2013-03-21 16:08:58

+0

@icepack'newBse'只是一个指针,当它返回时它指向一个局部变量。 – juanchopanza 2013-03-21 16:10:26

+0

@juanchopanza这是正确的,但这不是被问到的问题 – SomeWittyUsername 2013-03-21 16:11:43

回答

0

你有两个危险的缺陷

  • drvdCls newDrvd;声明在栈上的局部对象,并从函数返回后,它就会被破坏。那么指向newDrvdnewBse将无效。

  • &newDrvd指定给newBse后发生内存泄漏。

让我们来仔细看看:

bseCls* Test() 
{ 
    bseCls* newBse = new drvdCls(); // Allocates memory, newBse points to it 
    drvdCls newDrvd; // Allocates memory on local stack 
    newBse = &newDrvd; // newBse points to newDrvd (losts previous link - leak) 
    return newBse; // returns pointer to somewhere which is destroying 
} 
4

对象最初指向newBse会被泄露。当您将地址newDrvd分配给newBse时,您将丢失指向堆分配对象的指针,并且您将无法使用delete它。这个内存将不可用,直到进程终止。

  1. 对象的析构函数将被该函数返回前调用,这意味着你会:

    此外,您作为一个指针,这是坏的原因有两个返回堆栈分配对象的地址使用一个指向被破坏对象的指针。

  2. 为对象分配的内存位于堆栈上,几乎肯定会被未来的函数调用破坏。那时候,你的指针会指向一个不是bseCls的东西,但你会像使用它一样。

如果您使用此函数返回的指针,要调用未定义的行为和你的程序有牌做任何事情

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 d时,返回的unique_ptr超出范围。

+0

请注意'std :: unique_ptr <>'只能从C++ 11开启。根据这个函数的使用方式,'std :: auto_ptr <>'或'boost :: shared_ptr <>'对于较老的C++版本来说是一个很好的选择。 – cdhowie 2013-03-21 17:12:26