2017-03-06 35 views
2

我想知道如果这个代码,从加速C++ 14.1.2节,使得当fn被称为内存泄漏:这个“智能指针”代码会泄漏内存吗?

class IntPtr { 
public: 
    IntPtr(): p(NULL) {}; 
    IntPtr (int *ip): p(ip) {}; 
    IntPtr (const IntPtr& other) { p = new int(*other.p); }; 
    IntPtr& operator= (const IntPtr&); 
    ~IntPtr() { delete p; }; 

private: 
    int *p; 
} 

IntPtr& IntPtr::operator= (const IntPtr& other) { 
    if (&other != this) { delete p; p = new int(*other.p); } 
    return *this; 
} 

void fn() { 
    IntPtr a; 
    a = new int(9); 
} 

这里的到达路线a = new int(9)时,我觉得会发生什么:

  1. new int(9)用于分配存储器中的单个int(9)在堆中,并返回一个指向这个存储器(一个int *)。
  2. IntPtr是使用上面获得的int *和相应的构造函数创建的。
  3. IntPtr::operator=被称为,其中LHS a和IntPtr在上面创建为RHS。此操作为单个int分配另一块内存。该新块的地址存储在a.p中。

当到达最后一个大括号时,a被销毁,第二块内存与它一起销毁。我的问题是:第一个区块现在发生了什么?它还在堆上,没有指向它?行动2中创建的IntPtr的命运是什么?

+0

使用您的调试器,记下内存块的地址,单步执行代码。 –

+1

第2节的'IntPtr'是临时创建的。分配完成后它被销毁。为了说明会发生什么,请将输出添加到每个“IntPtr”方法,并且您将在控制台上看到它。 – Scheff

+0

在步骤2中创建的'intPtr'是一个临时的,并且在语句“a = new int(9)'完成时停止存在。 – Peter

回答

5

我的问题是:现在发生了什么第一块?它还在堆上,没有指向它? IntPtr在操作2中创建的命运是什么?

你可以重写这一行:

a = new int(9); 

为:分配将分配期间使用的临时对象中

a = IntPtr(new int(9)); 
    ^^^^^^ 

编译器创建。它的析构函数将在语句结尾处被调用(在行尾有分号)。

此代码看起来不错 - 不会发生内存泄漏。

+0

从内存泄漏的角度来看,代码看起来不错,但在其他方面缺乏(_i.e._它不是异常安全的)。 – You

+0

它看起来更像是关于班级如何工作的练习。 – marcinj