调用两次的析构函数会导致崩溃

Destructor called twice causes crash

本文关键字:析构函数 崩溃 两次 调用      更新时间:2023-10-16

我实现了一个以字符串为参数的构造函数,这会导致析构函数被调用两次,然后程序崩溃(程序包含一个原始指针(。我知道这与复制构造函数有关,当使用这种类型的构造函数时,复制构造函数会以某种方式被调用。下面是一个简单的代码来说明这个问题。

我很感激你对如何修复程序以避免其崩溃的评论。我需要使用这种构造函数。我想了解为什么会调用复制构造函数。我没有做任何明确的任务。

#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class DebugClass
{
public:
    DebugClass(void) {
        data = NULL;
    }
    DebugClass(std::string str) {
        data = new double[2];
        data[0] = 1.0;
        data[1] = 2.0;
    }
    DebugClass(DebugClass const& other) {
        cout << "copy constructionn"; 
    }
    ~DebugClass(void) {
        if (data)
        {
            delete [] data;
            data = NULL;
        }
    }
    double* data;
};

int main()
{
    DebugClass obj = DebugClass("Folder");
    return 0;
}

您的复制构造函数未初始化data

DebugClass::DebugClass(DebugClass const& other) 
{ 
    cout << "copy constructionn"; 
}

因此,从那时起,任何对数据的使用都会产生未定义的行为。

如果您只是在那里将data设置为nullptr,那么您不应该得到双重删除。尽管您可能真的想从other进行某种形式的复制。

此行:

DebugClass obj = DebugClass("Folder");

导致复制构造函数被调用作为构造CCD_ 5的一部分。

如果你改为:

DebugClass obj("Folder");

则CCD_ 6将用普通构造函数来构造。

DebugClass obj = DebugClass("Folder");

rhs创建一个无名称对象,并被分配给另一个新对象创建的obj,因此调用复制构造函数。

你的声明相当于

DebugClass obj1;
DebugClass obj2 = obj1; // here copy-ctor gets invoked

第二部分。。。尽管您已经定义了一个复制ctor,但它对您的程序几乎没有好处,因为您对指针数据成员没有做任何操作,该成员未初始化。这导致了未定义的行为。

虽然我不知道你对类DebugClass的意图,但用一种更简单的方式,它可以用另一个数据成员定义,比如array_size,你可以如下所示。

    DebugClass(void):array_size(0) {
    data = NULL;
}
DebugClass(std::string str, size_t aSize):array_size(aSize)
{
    if(array_size)
    {
       data = new double[array_size];
       data[0] = 1.0;
       data[1] = 2.0;
    }
}
DebugClass(DebugClass const& other):array_size(other.array_size)
{
    cout << "copy constructionn"; 
    if(array_size)
    {
       data = new double[array_size];
       for(int i=0; i<array_size; i++)
           data[i] = other.data[i];
    }
}

希望这能澄清。