所以我很好奇以下代码崩溃的原因。 非常感谢帮助。
#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;
}
答案 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)
您维护一个指针成员,并将该对象的副本传递给函数f
。因此,最终结果是您在同一指针上调用delete
两次。
答案 3 :(得分:1)
你在这里遇到的问题是双重删除。因为你没有在这里定义任何拷贝构造函数,所以C ++很高兴为你做到这一点。该实现通过执行所有内容的浅表副本来实现此目的。
f(x);
此行的工作原理是创建x
的副本并将其传递给f
。此时,有2个temp
个实例拥有一个intPtr
成员。两个实例都将删除该指针,这可能是导致崩溃的原因。
要解决此问题,您可以采取以下步骤
shared_ptr<T>
#2的一个例子是
class temp {
temp(const temp& other);
temp& operator=(const temp& other);
public:
// Same
};
现在f(x)
行根本无法编译,因为它无法访问必要的复制构造函数。它迫使它重新定义f
以防止复制。
void f(const temp& fInput) {
...
}