1

我遇到了这个链接,我看到了这个程序:

#include <iostream>
 
template<class T>
class Auto_ptr4
{
    T* m_ptr;
public:
    Auto_ptr4(T* ptr = nullptr)
        :m_ptr(ptr)
    {
    }
 
    ~Auto_ptr4()
    {
        delete m_ptr;
    }
 
    // Copy constructor
    // Do deep copy of a.m_ptr to m_ptr
    Auto_ptr4(const Auto_ptr4& a)
    {
        m_ptr = new T;
        *m_ptr = *a.m_ptr;
    }
 
    // Move constructor
    // Transfer ownership of a.m_ptr to m_ptr
    Auto_ptr4(Auto_ptr4&& a)
        : m_ptr(a.m_ptr)
    {
        a.m_ptr = nullptr; // we'll talk more about this line below
    }
 
    // Copy assignment
    // Do deep copy of a.m_ptr to m_ptr
    Auto_ptr4& operator=(const Auto_ptr4& a)
    {
        // Self-assignment detection
        if (&a == this)
            return *this;
 
        // Release any resource we're holding
        delete m_ptr;
 
        // Copy the resource
        m_ptr = new T;
        *m_ptr = *a.m_ptr;
 
        return *this;
    }
 
    // Move assignment
    // Transfer ownership of a.m_ptr to m_ptr
    Auto_ptr4& operator=(Auto_ptr4&& a)
    {
        // Self-assignment detection
        if (&a == this)
            return *this;
 
        // Release any resource we're holding
        delete m_ptr;
 
        // Transfer ownership of a.m_ptr to m_ptr
        m_ptr = a.m_ptr;
        a.m_ptr = nullptr; // we'll talk more about this line below
 
        return *this;
    }
 
    T& operator*() const { return *m_ptr; }
    T* operator->() const { return m_ptr; }
    bool isNull() const { return m_ptr == nullptr; }
};
 
class Resource
{
public:
    Resource() { std::cout << "Resource acquired\n"; }
    ~Resource() { std::cout << "Resource destroyed\n"; }
};
 
Auto_ptr4<Resource> generateResource()
{
    Auto_ptr4<Resource> res(new Resource);
    return res; // this return value will invoke the move constructor
}
 
int main()
{
    Auto_ptr4<Resource> mainres;
    mainres = generateResource(); // this assignment will invoke the move assignment
 
    return 0;
}

现在我看到这个程序很好,除了这部分:

// Copy assignment
// Do deep copy of a.m_ptr to m_ptr
Auto_ptr4& operator=(const Auto_ptr4& a)
{
   // Self-assignment detection
   if (&a == this)
      return *this;
 
   // Release any resource we're holding
   delete m_ptr;
 
   // Copy the resource
   m_ptr = new T;
   *m_ptr = *a.m_ptr;
 
    return *this;
}

我不明白为什么我们必须在delete m_ptr这里做。此外,如果m_ptr还没有动态分配会发生什么?然后我们将删除一个无效的指针。我们不能像这样不删除指针就保持原样吗?

// Copy assignment
// Do deep copy of a.m_ptr to m_ptr
Auto_ptr4& operator=(const Auto_ptr4& a)
{
   // Self-assignment detection
   if (&a == this)
      return *this;
 
   *m_ptr = *a.m_ptr;

    return *this;
}
4

1 回答 1

1

我不明白为什么我们必须delete m_ptr在这里做。

这是必要的,否则您可能会发生内存泄漏,因为new之前编辑的内存不会被delete编辑。

如果m_ptr还没有动态分配会发生什么,那么我们将delete是一个无效的指针。

如果Auto_ptr4什么都不做,m_ptr永远都是nullptr。默认构造函数初始化m_ptrnullptr,并且在移动m_ptr对象的移动操作之后也被分配为nullptr。在空指针上执行delete很好,它什么都不做。

如果表达式的计算结果为空指针值,则不调用析构函数,并且可能会或可能不会调用释放函数(未指定),但默认释放函数在传递空指针时保证不执行任何操作。

于 2020-07-29T02:16:42.063 回答