C++ Logo

std-discussion

Advanced search

Re: implicit lifetime and copy constructors

From: Federico Kircheis <federico_at_[hidden]>
Date: Fri, 24 Nov 2023 10:18:42 +0000
On 24 November 2023 09:24:45 UTC, Federico Kircheis via Std-Discussion <std-discussion_at_[hidden]> wrote:
>Hello, I have a question regarding implicit lifetimes and copy-constructors, maybe someone can help me.
>
>
>Consider following example
>
>----
>struct buff_int{
> unsigned char buffer[sizeof(int)];
> buff_int(int i){
> std::memcpy(buffer, &i, sizeof(int));
> }
> int get_int() const {
> int* j = std::launder(reinterpret_cast<int*>(buffer));
> return *j;
> }
>};
>
>auto val = buff_int(42);
>int i = val.get_int();
>----
>
>As far as I can see, everything is well-defined.
>std::memcpy creates implicitly an int object, and before accessing it, I'm using std::launder.
>
>But what about
>
>
>----
>struct buff_int{
> /* as before */
>};
>
>auto val = buff_int(42);
>int i = val.get_int();
>
>auto val2 = val;
>int i2 = val.get_int();
>----
>
>Is the line "int i2 = val.get_int();" well-defined?
>
>AFAIK the copy constructor does not necessarily call std::memcpy, so it does not seem defined that the buffer in val2 has an int object with implicit lifetime contained in the buffer.
>
>A similar question holds for the assignment operator.
>As assignment does not necessarily use memcpy, it does not seem to end and/or begin an implicit lifetime, thus
>
>----
>struct buff_int{
> /* as before */
>};
>
>auto val = buff_int(42);
>int i = val.get_int();
>
>auto val2 = buff_int(-1);
>val = val2;
>int i2 = val.get_int();
>----
>
>also seems to be UB.
>
>Thus to avoid UB/for having value semantic, the structure "buff_int" needs user-defined copy-constructor and assignment operator that uses memcpy internally, is that correct?

Sorry for the typo, should have written

int i2 = val2.get_int();

instead of

int i2 = val.get_int();

Received on 2023-11-24 10:18:46