Can you discard and place a new return value when initializing an object?


Lingxi

This question comes from the comments section of this thread , and there is an answer there as well. However, I think it is very important to only leave space in the comments section. So I did this Q&A.

new placement can be used to initialize objects in allocated storage, e.g.,

using vec_t = std::vector<int>;
auto p = (vec_t*)operator new(sizeof(vec_t));
new(p) vec_t{1, 2, 3}; // initialize a vec_t at p

According to cppref ,

new placement

If placement_params are provided, they are passed to the allocation function as additional parameters. This allocation function is called "placement new" after the standard allocation function, void* operator new(std::size_t, void*)and it simply returns its second argument . This is used to construct objects in allocated storage [...]

This means new(p) vec_t{1, 2, 3}return only p, and p = new(p) vec_t{1, 2, 3}seems redundant. Is it really okay to ignore the return value?

Lingxi

It is neither practical nor practical to ignore the return value.

From a scholarly point of view

For p = new(p) T{...}, pqualifies as a pointer to an object created by the new expression new(p) T{...}, although the value is the same, the new expression does not support for . In the latter case it can only be used as a pointer to allocated storage.

A non-allocation global allocation function returns its argument without any implicit side effects, but new-expression (placed or not) always returns a pointer to the object it created, even if the allocation function happens to be used.

Description of each cppref on delete-expression (emphasis mine) :

For the first (non-array) form, the expression must be a pointer to an object type or a class type to which the context is implicitly convertible to such a pointer, and its value must be null or a pointer to a non-array object created by new- . expression, or a pointer to the underlying subobject of the non-array object created by the new expression. If expression is anything else, including if it is a pointer obtained via the array form of new-expression, the behavior is undefined.

p = new(p) T{...}Therefore, failure will result in delete pundefined behavior.

From a practical point of view

Technically, without , it doesn't point to the newly initialized one p = new(p) T{...}, even if the actual value (memory address) is the same . Therefore, the compiler may assume that the code before the new placement is still referenced . Consider the codepTpT

p = new(p) T{...} // (1)
...
new(p) T{...} // (2)

Even after that (2), the compiler may make the wrong optimization by assuming that pthe old value initialized to is still referenced . For example, if you have a const member, the compiler might cache its value there and still use it even later .(1)T(1)(2)

p = new(p) T{...}This assumption is effectively prohibited. Another way is to use , but it's easier and cleaner to just assign the return value of where new is placed .std::launder()p

There are things you can do to avoid pitfalls

template <typename T, typename... Us>
void init(T*& p, Us&&... us) {
  p = new(p) T(std::forward<Us>(us)...);
}

template <typename T, typename... Us>
void list_init(T*& p, Us&&... us) {
  p = new(p) T{std::forward<Us>(us)...};
}

These function templates always set pointers internally. With available since C++17, the solution can be improved by automatically choosing between and based on whether the syntax is an aggregate type.std::is_aggregate(){}T

Related


How to return an object when initializing a variable in Java?

Nitin Khanna Is there any way to declare such static variables in java, for example, through them I can return the java object after initialization We can do it in python like this schedule.every(10).minutes.do(job) where, by calling every(10). Minutes I just

StackOverflow when initializing a new object

Served I don't know why this is happening, it seems to be in a constant loop between creating a new object and initializing it public class App { Character hero = new Character(); charCreation charCreation = new charCreation(); public static void main(String

Discard return value to return unit?

Dima I'm just starting with kotlin, so forgive me if this is a basic question, I did do some googling but didn't find anything useful. The question is how to convert the value to Unit. For example, in scala, if I write code like this: def foo: Int = ??? def ba

Discard return value to return unit?

Dima I'm just starting with kotlin, so forgive me if this is a basic question, I did do some googling but didn't find anything useful. The question is how to convert the value to Unit. For example, in scala, if I write code like this: def foo: Int = ??? def ba

Discard return value to return unit?

Dima I'm just starting with kotlin, so forgive me if this is a basic question, I did do some googling but didn't find anything useful. The question is how to convert the value to Unit. For example, in scala, if I write code like this: def foo: Int = ??? def ba

StackOverflow when initializing a new object

Served I don't know why this is happening, it seems to be in a constant loop between creating a new object and initializing it public class App { Character hero = new Character(); charCreation charCreation = new charCreation(); public static void main(String

Discard return value to return unit?

Dima I'm just starting with kotlin, so forgive me if this is a basic question, I did do some googling but didn't find anything useful. The question is how to convert the value to Unit. For example, in scala, if I write code like this: def foo: Int = ??? def ba

Discard return value to return unit?

Dima I'm just starting with kotlin, so forgive me if this is a basic question, I did do some googling but didn't find anything useful. The question is how to convert the value to Unit. For example, in scala, if I write code like this: def foo: Int = ??? def ba

How to return an object when initializing a variable in Java?

Nitin Khanna Is there any way to declare such static variables in java, for example, through them I can return the java object after initialization We can do it in python like this schedule.every(10).minutes.do(job) where, by calling every(10). Minutes I just