在下面的代码中,drvdCls
派生自bseCls
。此代码编译并按原样运行。然而,我在这里发现一个问题:在Test()
退出后,newBse
将被释放。我对吗?基础和派生类分配
bseCls* Test()
{
bseCls* newBse = new drvdCls();
drvdCls newDrvd;
newBse = &newDrvd;
return newBse;
}
在下面的代码中,drvdCls
派生自bseCls
。此代码编译并按原样运行。然而,我在这里发现一个问题:在Test()
退出后,newBse
将被释放。我对吗?基础和派生类分配
bseCls* Test()
{
bseCls* newBse = new drvdCls();
drvdCls newDrvd;
newBse = &newDrvd;
return newBse;
}
你有两个危险的缺陷
drvdCls newDrvd;
声明在栈上的局部对象,并从函数返回后,它就会被破坏。那么指向newDrvd
的newBse
将无效。
将&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
}
对象最初指向newBse
会被泄露。当您将地址newDrvd
分配给newBse
时,您将丢失指向堆分配对象的指针,并且您将无法使用delete
它。这个内存将不可用,直到进程终止。
此外,您作为一个指针,这是坏的原因有两个返回堆栈分配对象的地址使用一个指向被破坏对象的指针。
bseCls
的东西,但你会像使用它一样。如果您使用此函数返回的指针,要调用未定义的行为和你的程序有牌做任何事情。
不,它不会被自动解除分配。致电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
超出范围。
请注意'std :: unique_ptr <>'只能从C++ 11开启。根据这个函数的使用方式,'std :: auto_ptr <>'或'boost :: shared_ptr <>'对于较老的C++版本来说是一个很好的选择。 – cdhowie 2013-03-21 17:12:26
不,它不会。这是动态内存分配的重点。但是,在代码中存在严重的问题 - 您将指针指向已分配的内存,并返回一个指向自动变量的指针(在func退出时将释放此指针,最终将解决函数调用器中释放的内存)。 – SomeWittyUsername 2013-03-21 16:08:58
@icepack'newBse'只是一个指针,当它返回时它指向一个局部变量。 – juanchopanza 2013-03-21 16:10:26
@juanchopanza这是正确的,但这不是被问到的问题 – SomeWittyUsername 2013-03-21 16:11:43