复制构造函数

时间:2016-02-27 10:00:24

标签: c++

我试图理解复制构造函数的概念。我用这个例子:

#include <iostream>

using namespace std;

class Line
{
public:
    int GetLength();
    Line(int len);
    Line(const Line &obj);
    ~Line();

private:
    int *ptr;
};

Line::Line(int len)
{
    ptr = new int;
    *ptr = len;
};

Line::Line(const Line &obj)
{
    cout << "Copying... " << endl;
    ptr = new int;
    *ptr = *obj.ptr;
};

Line::~Line()
{
    delete ptr;
};

int Line::GetLength()
{
    return *ptr;
}

int main()
{
    Line line1 = Line(4);
    cout << line1.GetLength() << endl;

    Line line2 = line1;
    line1.~Line();

    cout << line2.GetLength() << endl;

    return 0;
}

问题是,为什么我在这里遇到运行时错误?如果我定义了一个复制构造函数,它为新的ptr分配内存,并将line1分配给line2,那是不是意味着这两个是单独的对象?通过破坏line1,我显然也搞乱了line2,或者我使用析构函数调用错了?

2 个答案:

答案 0 :(得分:7)

您在此声明中调用了析构函数

line1.~Line();

删除了为ptr

分配的内存
Line::~Line()
{
    delete ptr;
};

然而,对象line1仍然存在,因为它具有自动存储持续时间。因此,在退出main之后,将再次调用该对象的析构函数,因此它将尝试删除已明确删除的ptr指向的内存。

答案 1 :(得分:0)

line1.~Line();

仅当您使用展示位置新时,手动调用析构函数才有用。

我不明白是什么让你想到在这个程序中手动调用析构函数。当你还不熟悉这种语言时,你真的不想知道这种低级别的内存管理机制,但为了完整起见,它会像这样工作:

int main()
{
    // provide static memory with enough space for one Line object:
    char buffer[sizeof(Line)];

    // create a Line object and place it into buffer:
    Line* line1 = new (buffer) Line(4);

    cout << line1->GetLength() << endl;

    Line line2 = *line1;

    // manually call the destructor:
    line1->~Line();

    cout << line2.GetLength() << endl;

    // - no delete necessary because buffer disappears automatically
    // - no automatic destructor call

    return 0;
}

但是,您的代码会导致尝试两次调用line1的析构函数。首先手动,然后在对象的范围结束时自动,即在main结束时。这是未定义的行为。见Does explicitly calling destructor result in Undefined Behavior here?

  

问题是,为什么我在这里遇到运行时错误?

因为未定义的行为意味着您的程序可以执行或不执行任何操作。不保证运行时错误,也不保证任何确定性行为。