2014-12-09 11 views
1
#include <iostream> 
using namespace std; 
static int i=1; 
class Parent 
{ 
public: 
    virtual ~Parent(){10/i;} 
}; 

class Child: public Parent 
{ 
public: 
    virtual ~Child(){--i;} 
}; 

int main() 
{ 
    Parent *ptr = new Parent; 
    Parent *ptr1 = new Child; 
    delete ptr; 
    delete ptr1; 
    //cout<<10/i; 
    return 0; 
} 

Почему виртуальный деструктор класса Parent не предоставляет никаких ошибок во время выполнения? Принимая во внимание, что прокомментированная часть кода выдает ошибку при раскомментировании.Подразделение на нуль отлично работает в виртуальном деструкторе

+0

'cout << 10/i;' также не будет работать в виртуальном деструкторе. Виртуальный деструктор полностью не связан с вашим вопросом. – hvd

+5

Этот оператор ('10/i;') не имеет побочных эффектов, компилятор, по-видимому, оптимизирует его. –

+0

Обратите внимание, что gcc и clang выдают предупреждение «инструкция не имеет эффекта» для вышеуказанного кода. –

ответ

5

Я думаю, ваш компилятор оптимизирует код и удаляет бесполезную часть, включая 10/i в деструкторе базового класса.

Попробуйте с this:

#include <iostream> 
using namespace std; 
static int i=1; 
class Parent 
{ 
public: 
    virtual ~Parent(){int tmp = 10/i; cout << tmp; } 
}; 

class Child: public Parent 
{ 
public: 
    virtual ~Child(){--i;} 
}; 

int main() 
{ 
    Parent *ptr = new Parent; 
    Parent *ptr1 = new Child; 
    delete ptr; 
    delete ptr1; 
    //cout<<10/i; 
    return 0; 
} 
5

Неопределенное поведение не определено, так что все может случиться.

Утверждение без побочных эффектов тривиально для компилятора, чтобы его оптимизировать, поэтому он даже не пытается выполнить то, что находится внутри базового деструктора.

Имея это в cout, это другое дело - вы попробовали оба?

+4

:(богатые становятся богаче. Мне жаль, что мои воображаемые интернет-точки не были деньгами. –

+0

@nouney Я не голосовал ни на одном из ответов, но для меня этот ответ легче понять, чем ваш, и это обычно является причиной для я должен поддержать этот ответ и не голосовать (ни вверх, ни вниз) на вашем. Это было бы не из-за вашей репутации вообще. – hvd

+0

@hvd Я не думаю, что он имел в виду моего представителя. Я нахожусь в шестизначном значении , черт возьми! –

1

Независимо от того, что нет никакого наблюдаемого поведения, это довольно легко для компилятора, чтобы доказать, что --i утверждение всегда сопровождается 10/i, что в свою очередь означает, что --i нельзя назвать для i==1.

С i является статичным для модуля перевода, оптимизатор также знает, что нет другого кода, изменяющего i от его начального значения 1.

Таким образом, современный оптимизатор может доказать, что Child::~Child не называется.

В свою очередь, это означает, что четвертая строка main недоступна. Здесь все может стать действительно забавным. main, по-видимому, свободен от ветвей, но для компилятора это не так. new может бросать, что вводит две ветви в эту программу. И так как «обычная» ветвь без исключения доказуемо не может быть выполнена, оптимизатор может заключить, что единственными доступными ветвями являются 2, где либо new оператор выдает (!)