-1

私はMSVisualStudio2010を使用しています。

二重リンクリストを実装しました。

オブジェクトのデストラクタを呼び出すメソッドCleanを呼び出した後のメイン関数で、オブジェクトを参照した後、エラーが発生しないのはなぜだろうか。

これが私の二重リンクリストメソッドのいくつかです(私の質問に関連して):

/*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

ここで考慮すべき重要なことは、オブジェクトの存続期間です。オブジェクトの存続期間は、そのオブジェクトのストレージが割り当てられた時間内に存在する必要があります。多くのオブジェクトは、ストレージが割り当てられている時間内に1つのストレージロケーションに次々と存在する可能性があります。

通常、オブジェクトが破棄されると(スコープ外になるか、を呼び出すことによってdelete)、オブジェクトの有効期間が終了し、そのメモリの割り当てが解除されます。ただし、デストラクタを明示的に呼び出す場合は、オブジェクトの存続期間を終了するだけです。この規格には、「存在しない」オブジェクトの定義はありませんが、存続期間が終了するという概念はあります。

タイプのオブジェクトの存続期間は、次の場合にT終了します。

  • Tが自明でないデストラクタ(12.4)を持つクラス型の場合、デストラクタ呼び出しが開始されます。
  • オブジェクトが占有するストレージは、再利用または解放されます。

現在、オブジェクトの有効期間が終了した後、ストレージの割り当てが解除される前の状態では、実行できるのは非常に具体的なことだけです。この標準では、この状態でポインターとglvalueの両方に対して実行できることを定義しています。あなたの場合、listはglvalueなので、そのためのルールを見ていきます。

[...]オブジェクトの存続期間が終了した後、オブジェクトが占有していたストレージが再利用または解放される前に、元のオブジェクトを参照するglvalueを使用できますが、その方法は限られています。[...]次の場合、プログラムの動作は未定義です。

  • 左辺値から右辺値への変換(4.1)は、このようなglvalueに適用されます。
  • glvalueは、非静的データメンバーにアクセスするため、またはオブジェクトの非静的メンバー関数を呼び出すために使用されます。
  • glvalueは暗黙的に基本クラスタイプへの参照に変換されます(4.10)、または
  • static_castglvalueは、変換が最終的にcvchar&またはcvunsigned char&になる場合を除いて、(5.2.9)のオペランドとして使用されます。
  • glvalueは、dynamic_cast(5.2.7)のオペランドまたは。のオペランドとして使用されtypeidます。

2番目のリスト項目がここに適用されます。オブジェクトの有効期間が終了した後に非静的メンバー関数にアクセスしているため、未定義の動作があります。

于 2013-02-28T09:48:18.950 に答える
2

オブジェクトが破棄された後(つまり、デストラクタが呼び出された後)にオブジェクトを使用します。UBは未定義の動作を意味します。それで...

于 2013-02-28T08:50:49.480 に答える