Date: Mon, 29 Apr 2019 12:07:25 +0200
what does "and/or not reassignable buffer" mean?
On Mon, Apr 29, 2019 at 11:54 AM Nicolas Lesser <blitzrakete_at_[hidden]>
wrote:
> Mohamed Khaled via Std-Discussion wrote:
> > Hello All,
> >
> > ```
> > #include <memory>
> > #include <iostream>
> >
> > struct C
> > {
> > const int x;
> > };
> >
> > void foo1()
> > {
> > C c{1};
> > c.~C();
> > new (&c) C{2};
> > std::cout << c.x << std::endl;
> > }
> >
> > std::unique_ptr<C> foo2_a()
> > {
> > std::unique_ptr<C> c(new C{1});
> > c->~C();
> > new (c.get()) C{2};
> > return c;
> > }
> >
> > void foo2_b(std::unique_ptr<C> c)
> > {
> > std::cout << c->x << std::endl;
> > }
> >
> > int main()
> > {
> > foo1();
> > foo2_b(foo2_a());
> > }
> > ```
> >
> > As far as I understand, in foo1() one should invoke std::launder
> whenever c
> > is being accessed after the placement. Should it also be invoked in
> foo2_b,
> > that is when the access to the object whose memory is being reused is in
> > some separate function rather than the one where the placement happened.
>
> std::launder is used only when you only have access to the new element
> through the old object, when for example the class has a const data member.
> In your case, you are right that in foo1 you should use std::launder. This
> *also* applies to foo2_b, since the pointer stored in the unique_ptr points
> to the old object and it can only be used to access the new object with
> std::launder.
>
> > More generally should the placement new always be coupled with
> std::launder?
>
> Not necessarely, only when you are using placement new on a variable
> and/or not reassignable buffer. If you use a pointer for example you can do
> this:
>
> ptr = new (ptr) C{2};
>
> And there you don't have to use placement new.
>
> --
> - Nicolas
>
On Mon, Apr 29, 2019 at 11:54 AM Nicolas Lesser <blitzrakete_at_[hidden]>
wrote:
> Mohamed Khaled via Std-Discussion wrote:
> > Hello All,
> >
> > ```
> > #include <memory>
> > #include <iostream>
> >
> > struct C
> > {
> > const int x;
> > };
> >
> > void foo1()
> > {
> > C c{1};
> > c.~C();
> > new (&c) C{2};
> > std::cout << c.x << std::endl;
> > }
> >
> > std::unique_ptr<C> foo2_a()
> > {
> > std::unique_ptr<C> c(new C{1});
> > c->~C();
> > new (c.get()) C{2};
> > return c;
> > }
> >
> > void foo2_b(std::unique_ptr<C> c)
> > {
> > std::cout << c->x << std::endl;
> > }
> >
> > int main()
> > {
> > foo1();
> > foo2_b(foo2_a());
> > }
> > ```
> >
> > As far as I understand, in foo1() one should invoke std::launder
> whenever c
> > is being accessed after the placement. Should it also be invoked in
> foo2_b,
> > that is when the access to the object whose memory is being reused is in
> > some separate function rather than the one where the placement happened.
>
> std::launder is used only when you only have access to the new element
> through the old object, when for example the class has a const data member.
> In your case, you are right that in foo1 you should use std::launder. This
> *also* applies to foo2_b, since the pointer stored in the unique_ptr points
> to the old object and it can only be used to access the new object with
> std::launder.
>
> > More generally should the placement new always be coupled with
> std::launder?
>
> Not necessarely, only when you are using placement new on a variable
> and/or not reassignable buffer. If you use a pointer for example you can do
> this:
>
> ptr = new (ptr) C{2};
>
> And there you don't have to use placement new.
>
> --
> - Nicolas
>
Received on 2019-04-29 05:09:15