Как std :: cout изменяет поведение деструктора при явном вызове в этом случае? - PullRequest
0 голосов
/ 20 октября 2018

Я экспериментирую с явным вызовом деструктора объекта.Следующий код работает должным образом:

class Foo {
    public:

    ~Foo() {
        x_=x_+10;
        std::cout << "x_ = " << x_ << std::endl;
    }

    int x() {
        return x_;
    }
    int x_=0;
};


int main()
{
    Foo f;
    std::cout << "f.x() = " << f.x() << std::endl;

    f.~Foo();
    f.~Foo();

    std::cout << "f.x() = " << f.x() << std::endl;
    return 0;
}

И распечатка:

f.x() = 0                                                                                                                                                      
x_ = 10                                                                                                                                                        
x_ = 20                                                                                                                                                        
f.x() = 20                                                                                                                                                     
x_ = 30

Как и ожидалось, каждый раз, когда вызывается деструктор, x_ увеличивается на 10, поэтому мы видимпрогрессия от 10 до 20 до 30.

Однако, если мы удалим std::cout из деструктора, например:

class Foo {
    public:

    ~Foo() {
        x_=x_+10;
    }

    int x() {
        return x_;
    }
    int x_=0;
};


int main()
{
    Foo f;
    std::cout << "f.x() = " << f.x() << std::endl;

    f.~Foo();
    f.~Foo();

    std::cout << "f.x() = " << f.x() << std::endl;
    return 0;
}

Тогда распечатка станет:

f.x() = 0                                                                                                                                                      
f.x() = 0 

Приращение в деструкторе больше не работает.Может кто-нибудь объяснить, почему на поведение деструктора может повлиять оператор print?

Ответы [ 3 ]

0 голосов
/ 20 октября 2018

Использование уничтоженного объекта - неопределенное поведение.Таким образом, любые изменения в объекте stste в деструкторе не будут заметны после его завершения.

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

При последующей печати можно скопировать значение, добавить 10, а затем распечатать копию.Но вместо этого компилятор увеличивает его на месте и печатает его.

Программы с неопределенным поведением не имеют ограничений на свое поведение как до, так и после неопределенного поведения в соответствии со стандартом C ++.

0 голосов
/ 20 октября 2018
{
    Foo f;
    f.~Foo();
}

Это неопределенное поведение.f - переменная с автоматической продолжительностью хранения.Это означает, что его время жизни управляется автоматически, и вы не можете явно прекратить его жизнь.

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

0 голосов
/ 20 октября 2018
f.~Foo();
f.~Foo();

Не надо.Просто не надо.Это плохо.Очень плохой.Никогда не делайте этого, особенно если вы не понимаете, что такое деструктор.

Компилятор просто пропускает код, потому что это неизведанная территория, и он делает все, что хочет в этом случае.

Явный деструктор не работает

...