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

I have never seen this idiom, and it seems like it could be really subtle and messy, but I can't actually think of a problem with it (as long as FooView is final). Is this a bad idea?

luqui
  • 59,485
  • 12
  • 145
  • 204
  • related/dupe: https://stackoverflow.com/questions/58274963/placement-new-on-non-pointer-variables-and-class-members. Can we get the full context of the type? It does matter. – NathanOliver Jan 10 '20 at 21:38

1 Answers1

12

You can do that, but you'll need memory laundering for that if you have reference or const members, or if the type of the class changes.

Consider this:

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?
}

To avoid this undefined behaviour, you should launder the memory using std::launder. The compiler will assume that the lifetime of fv won't be affected by anything except }. Laundering will make the compiler assume there is an object, unrelated to fv:

int main() {
    FooView fv{9};

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

Now is it a good idea? I'd advise against it since it can lead to confusion but it can be done safely.

Evg
  • 25,259
  • 5
  • 41
  • 83
Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141