-1

我使用 MS Visual Studio 2010。

我实现了一个双链表。

我想知道为什么在调用方法 Clean 之后的 main 函数中,它调用对象的析构函数,在我引用对象之后没有引发错误。

这是我的一些双链表方法(相对于我的问题):

/*DoubleLinkedList.cpp */  
         DoubleLinkedList::~DoubleLinkedList(void)
        {
        cout << "Destructor invoked" << endl;
        // as for data nodes memory is allocated in heap we have to release it:
        const Node* const_iterator = m_head.m_next;
        while (const_iterator != &m_tail)
        {
            const_iterator = const_iterator->m_next;
            delete const_iterator->m_prev;
        }
    }

void DoubleLinkedList::Clean(void)
{
    cout << "Clean invoked" << endl;

    this->~DoubleLinkedList(); /* According to C++ 11 standart: Once a destructor is invoked for an object, the object no longer exists*/
}

/* main.cpp */
    int main(int argc, char* argv[])
    {
        DoubleLinkedList list;
        Circle c1, c2(MyPoint(1,1),50), c3(MyPoint(2,2),30);
        list.Front(&c1);
        list.Front(&c2);
        list.Front(&c3);
        list.Show();
        list.Sort();
        list.Show();
        list.Clean();
        list.Show(); /* Recall how Clean method is implemented. As list no longer exist, run-time error is expected here, but flow of executon continues and Show, Push_back preforms fine*/
        list.Push_back(&c1);
        list.Push_back(&c2);
        list.Push_back(&c3);

问题: *如调用析构函数后的 C++ 11 标准中所述 - 对象不再存在*,为什么在调用析构函数后我仍然能够使用该对象?

4

2 回答 2

3

这里要考虑的重要一点是对象的生命周期。对象的生命周期必须存在于为该对象分配存储空间的时间内。在分配存储的时间内,许多对象可以一个接一个地存在于单个存储位置。

通常,当一个对象被销毁(通过超出范围或调用delete)时,对象的生命周期结束,然后它的内存被释放。但是,当您显式调用析构函数时,您所做的只是结束对象的生命周期。该标准没有定义对象“不存在”,但确实有其生命周期结束的概念。

类型对象的生命周期在以下情况下T结束:

  • 如果T是具有非平凡析构函数(12.4)的类类型,则析构函数调用开始,或者
  • 对象占用的存储空间被重用或释放。

现在,在对象生命周期结束之后和其存储被释放之前的状态下,您只能做一些非常具体的事情。该标准定义了在这种状态下可以对指针和glvalues执行的操作。在你的情况下,list是一个glvalue,所以我们将看看它的规则:

[...] 在对象的生命周期结束之后和对象占用的存储空间被重用或释放之前,可以使用任何引用原始对象的泛左值,但只能以有限的方式使用。[...]如果出现以下情况,该程序具有未定义的行为:

  • 左值到右值的转换(4.1)应用于这样的左值,
  • glvalue 用于访问非静态数据成员或调用对象的非静态成员函数,或
  • glvalue 被隐式转换(4.10)为对基类类型的引用,或者
  • 泛左值用作static_cast(5.2.9) 的操作数,除非转换最终为 cvchar&或 cv unsigned char&,或
  • 泛左值用作dynamic_cast(5.2.7) 的操作数或typeid.

第二个列表项适用于此。您有未定义的行为,因为您在对象生命周期结束后访问非静态成员函数。

于 2013-02-28T09:48:18.950 回答
2

Use object AFTER it's destroyed (i.e. destructor's is called) is UB. UB means undefined behaviour. So...

于 2013-02-28T08:50:49.480 回答