Date: Fri, 24 Nov 2023 19:18:09 +0000
Yes, I see now that I mixed up 'new' and 'operator new' and now I understand
the difference between them.
Thank you for the clarification!
So as I understand it I do the following?
// C++20
S s;
std::byte buffer[sizeof(S)];
read_from_file(buffer);
std::memcpy(&s, buffer, sizeof(s));
// C++23
S s;
read_from_file(reinterpret_cast<std::byte*>(&s), sizeof(s));
std::start_lifetime_as<S>(&s);
Best regards,
Daniel
________________________________
From: Jens Maurer <jens.maurer_at_[hidden]>
Sent: Thursday, November 23, 2023 22:38
To: std-discussion_at_[hidden] <std-discussion_at_[hidden]>
Cc: Daniel Markus <daniel_at_[hidden]>
Subject: Re: [std-discussion] Inconsistency in Examples
On 23/11/2023 20.47, Daniel Markus via Std-Discussion wrote:
> Hi!
>
> I'm trying to learn about object lifetime and am reading the specification. When I was reading
> §6.7.3/8 I realized that the example discards the return value from placement new, but that has
> the [[nodiscard]] attribute (§17.6.3.4/1).
> https://en.cppreference.com/w/cpp/memory/new/operator_new <https://en.cppreference.com/w/cpp/memory/new/operator_new>
You're looking at the declaration of "operator new", but you've
written a new-expression in your example. It's not clear to me
that [[nodiscard]] on the former has any effect on the latter.
In any case, [[nodiscard]] asks the implementation to issue a
warning under certain circumstances, nothing else. Normative
behavior is not affected by [[nodiscard]].
> Following is a situation I have where I want to ensure the lifetime of the object.
>
> struct S
> {
> int i;
> };
>
> int main()
> {
> S s = {};
>
> read_from_file(reinterpret_cast<std::byte*>(&s));
> new(&s) S; // Start lifetime (§6.7.2/13).
> // or
> std::start_lifetime_as<S>(&s); // C++23.
>
> s.i += s.i; // Use data with old reference (§6.7.3/8).
>
> return 0;
> }
>
> According to §6.7.3/5 and §6.7.3/8 I can read data directly into the struct s.
I'm not reading that from the cited sections. You're certainly ending
the lifetime of "s" when scribbling over its object representation, though.
> The only thing left is
> to start the lifetime of the new object.
> My questions are:
>
> * If placement new is [[nodiscard]] I guess that I must use the returning pointer?
[[nodiscard]] does not cause any "must".
> * std::start_lifetime_as is not [[nodiscard]]. Does it mean that discarding its return value will work?
In either case, the return values are helpful in case you're dealing with non-transparently
replaceable objects.
I'd like to point out that "new" creates an object on storage with indeterminate value
(i.e. the compiler can consider stores to the storage before the placement-new as dead),
whereas start_lifetime_as is expressly specified to reuse the contents of the storage.
Jens
the difference between them.
Thank you for the clarification!
So as I understand it I do the following?
// C++20
S s;
std::byte buffer[sizeof(S)];
read_from_file(buffer);
std::memcpy(&s, buffer, sizeof(s));
// C++23
S s;
read_from_file(reinterpret_cast<std::byte*>(&s), sizeof(s));
std::start_lifetime_as<S>(&s);
Best regards,
Daniel
________________________________
From: Jens Maurer <jens.maurer_at_[hidden]>
Sent: Thursday, November 23, 2023 22:38
To: std-discussion_at_[hidden] <std-discussion_at_[hidden]>
Cc: Daniel Markus <daniel_at_[hidden]>
Subject: Re: [std-discussion] Inconsistency in Examples
On 23/11/2023 20.47, Daniel Markus via Std-Discussion wrote:
> Hi!
>
> I'm trying to learn about object lifetime and am reading the specification. When I was reading
> §6.7.3/8 I realized that the example discards the return value from placement new, but that has
> the [[nodiscard]] attribute (§17.6.3.4/1).
> https://en.cppreference.com/w/cpp/memory/new/operator_new <https://en.cppreference.com/w/cpp/memory/new/operator_new>
You're looking at the declaration of "operator new", but you've
written a new-expression in your example. It's not clear to me
that [[nodiscard]] on the former has any effect on the latter.
In any case, [[nodiscard]] asks the implementation to issue a
warning under certain circumstances, nothing else. Normative
behavior is not affected by [[nodiscard]].
> Following is a situation I have where I want to ensure the lifetime of the object.
>
> struct S
> {
> int i;
> };
>
> int main()
> {
> S s = {};
>
> read_from_file(reinterpret_cast<std::byte*>(&s));
> new(&s) S; // Start lifetime (§6.7.2/13).
> // or
> std::start_lifetime_as<S>(&s); // C++23.
>
> s.i += s.i; // Use data with old reference (§6.7.3/8).
>
> return 0;
> }
>
> According to §6.7.3/5 and §6.7.3/8 I can read data directly into the struct s.
I'm not reading that from the cited sections. You're certainly ending
the lifetime of "s" when scribbling over its object representation, though.
> The only thing left is
> to start the lifetime of the new object.
> My questions are:
>
> * If placement new is [[nodiscard]] I guess that I must use the returning pointer?
[[nodiscard]] does not cause any "must".
> * std::start_lifetime_as is not [[nodiscard]]. Does it mean that discarding its return value will work?
In either case, the return values are helpful in case you're dealing with non-transparently
replaceable objects.
I'd like to point out that "new" creates an object on storage with indeterminate value
(i.e. the compiler can consider stores to the storage before the placement-new as dead),
whereas start_lifetime_as is expressly specified to reuse the contents of the storage.
Jens
Received on 2023-11-24 19:18:12