你能告诉我为什么这段代码会崩溃吗?

时间:2012-04-04 21:16:37

标签: c++ class function pointers crash

所以我很好奇以下代码崩溃的原因。 非常感谢帮助。

#include <iostream>
using namespace std;

class temp
{    
  public:

    temp(int i)
    {
        intPtr = new int(i);
    }

    ~temp()
    {
        delete intPtr;
    }

  private:
    int* intPtr;
};

void f (temp fInput)
{
    cout << "f called" << endl;
}

int main()
{
    temp x = 2;
    f(x);
    return 0;
}

4 个答案:

答案 0 :(得分:5)

当传递x时(隐式复制构造函数)复制指针,并且两次调用析构函数(在函数返回之前和main返回之前),因此内存将被删除两次。

此处使用std::shared_ptr<int>而不是原始int指针(假设您希望行为相同,即从int引用相同的temp;否则,实现复制构造函数,自己移动构造函数和赋值操作符。)

#include <memory>

class temp {    
public:
  temp(int i) : intPtr(std::make_shared<int>(i)) {

  }

private:
  std::shared_ptr<int> intPtr; // reference counting ftw
};

答案 1 :(得分:5)

由于您传递x的方式而发生崩溃。

f函数的范围之后,将调用x的destructure并删除intPtr

但是,这将删除仍在main范围内的内存。因此,在调用return 0之后,它将尝试删除已存在的内存,因为您在同一指针上调用了两次删除。

要修复此错误,请更改

void f (temp fInput)

void f (const temp& fInput)

或者,您可以考虑使用std::shared_ptr

答案 2 :(得分:5)

您违反了The Rule of Three

您维护一个指针成员,并将该对象的副本传递给函数f。因此,最终结果是您在同一指针上调用delete两次。

答案 3 :(得分:1)

你在这里遇到的问题是双重删除。因为你没有在这里定义任何拷贝构造函数,所以C ++很高兴为你做到这一点。该实现通过执行所有内容的浅表副本来实现此目的。

f(x);  

此行的工作原理是创建x的副本并将其传递给f。此时,有2个temp个实例拥有一个intPtr成员。两个实例都将删除该指针,这可能是导致崩溃的原因。

要解决此问题,您可以采取以下步骤

  1. 使用用于共享的指针类型,如shared_ptr<T>
  2. 创建一个不可调用的复制构造函数,强制实例由ref
  3. 传递

    #2的一个例子是

    class temp {
      temp(const temp& other);
      temp& operator=(const temp& other);
    public:
      // Same
    };
    

    现在f(x)行根本无法编译,因为它无法访问必要的复制构造函数。它迫使它重新定义f以防止复制。

    void f(const temp& fInput) {
      ...
    }