何时对使用`new`创建的临时对象调用'delete'?

时间:2013-09-25 18:19:38

标签: c++ new-operator delete-operator temporary

我使用new Time(1,0,0)初始化SmartPtr类。

    //main.cpp 
    int main()
{
    SmartPtr pTime0(new Time(0,0,1));
}

我无法在new Time(1,0,0)上调用删除。一切正常,程序符合并运行。但我很困惑 - 应该/不应该在哪里delete Time(1,0,0)

我不明白在这里创建和删除临时对象的概念。 我知道每当我写new某处我必须写delete! 有人可以解释delete Time(1,0,0)发生在哪里吗?

SmartPtr pTime0(新时间(0,0,1))< - new这里返回一个指向新分配内存的指针,然后在ctor中我第二次分配new内存??

//SmartPtr.cpp 

SmartPtr::SmartPtr(Pointee * p):_pointee(new Pointee(*p))
{}

SmartPtr::~SmartPtr()
{
    delete _pointee; 
}

4 个答案:

答案 0 :(得分:2)

我不知道您SmartPtr课程的详细信息。

无论如何,如果你有这样的构造函数:

SmartPtr::SmartPtr(Pointee * p):_pointee(new Pointee(*p))
{}

这是析构函数:

SmartPtr::~SmartPtr()
{
    delete _pointee; 
}

然后使用此代码:

SmartPtr pTime0(new Time(0,0,1));

泄漏了Time(0,0,1)的一个实例。

事实上,您还有一个new而非delete(2 new s和1 delete):

步骤1:你调用new Time(0,0,1)并在堆上创建一个新对象 (new count == 1)

步骤2:您将此指针传递给SmartPtr构造函数,深层复制以前创建的对象并在堆上分配新副本,并通过其{跟踪此副本{1}}数据成员。
_pointee count == 2)

步骤3:当new析构函数运行时,它SmartPtrdelete数据成员指向的实例,但是你泄露了 firts {{ 1}}在_pointee的堆上创建 (Time(...) count == 1; new Time(0,0,1) count == 2)

可能的解决办法就是拥有这个构造函数:

delete

在这些情况下识别潜在泄漏的一种简单方法是在new类构造函数和析构函数中放置一些控制台跟踪输出,并检查析构函数的跟踪输出是否与构造函数的跟踪输出匹配,例如:

SmartPtr::SmartPtr(Pointee * p)
    : _pointee(p) // <--- transfer ownerhsip (no deep copies) !
{}

Time字符串的总数应与Time::Time(....) { // Do construction work.... std::cout << "Time constructor\n"; } Time::~Time(....) { // Do destructor work.... std::cout << "Time destructor\n"; } 字符串的总数相匹配。

答案 1 :(得分:1)

两种解决方法:

方法A,调用者分配,SmartPtr取得所有权:

SmartPtr::SmartPtr(Pointee * p):_pointee(p)
{
}

方法B,调用者提供内容,SmartPtr分配:

SmartPtr::SmartPtr(Pointee v):_pointee(new Pointee(std::move(v)))
{
}

析构函数保持不变:

SmartPtr::~SmartPtr()
{
    delete _pointee; 
}

答案 2 :(得分:0)

表达式new Time(0,0,1)创建一个指向堆上永久对象的临时指针。确实会自动销毁临时指针(这是一个无操作),使对象仍然在堆上但未引用。发生了泄漏。

为了防止泄漏,请确保将指针存储在某处,并确保最终在其上调用删除。

答案 3 :(得分:0)

您可以根据从不输入新的原则编写应用程序。
将它与现有的智能指针结合起来,它就变成了:

#include <memory>    // this is where the smart-pointers live
#include "Time.h"    // or whatever header defines your "Time" class

int main()
{
    // note that make_shared is essentially a forwarding constructor,
    // give it whatever parameters Time's constructor would take
    auto p = std::make_shared<Time>(0,0,1); 
    // use p here
}

任何事情都不会泄漏。

“从不输入新”应适用于所有应用程序编程, 如果你必须写一个低级别,唯一的例外 资源管理库。

请注意,如果一个类进行资源管理,它应该是它的 唯一的功能。

所有其他课程都应遵循rule of zero