Чи є нова (ця) ця класифікація () поганою ідеєю?


9
class FooView final : public Something
{
    ...
    void refresh()
    {
        this->~FooView();
        new (this) FooView();
    }
}

Я ніколи не бачив цієї ідіоми, і мені здається, що вона може бути справді тонкою і безладною, але насправді я не можу думати про проблему з цим (доки FooViewвона остаточна). Це погана ідея?


пов'язані / дуп: stackoverflow.com/questions/58274963/… . Чи можемо ми отримати повний контекст типу? Це має значення.
NathanOliver

Відповіді:


12

Ви можете це зробити, але для цього вам знадобиться відмивання пам'яті, якщо у вас є посилання або члени const або якщо тип класу змінюється.

Врахуйте це:

struct FooView {
    const int val;

    void refresh()
    {
        this->~FooView();
        new (this) FooView{5};
    }
}

int main() {
    FooView fv{9};

    std::cout << fv.val; // surely 9!
    fv.refresh();
    std::cout << fv.val; // hmm... val is a const object, so it's 9 still?
}

Щоб уникнути цього невизначеного поведінки, слід відмити пам'ять, використовуючи std::launder. Компілятор припустить, що на життя fvне вплине нічого, крім }. Відмивання змусить компілятор припустити, що існує об'єкт, не пов'язаний з fv:

int main() {
    FooView fv{9};

    std::cout << fv.val; // surely 9!
    fv.refresh();
    std::cout << std::launder(&fv)->val; // yay, 5
}

Тепер це гарна ідея? Я б радив проти цього, оскільки це може призвести до плутанини, але це можна зробити безпечно.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.