When using placement new in generic code to construct an object at a specified address, the usage pattern is a bit different from usual code. For example, consider this implementation of uninitialized_copy
: ( [uninitialized.copy] )
template <class It, class For>
For uninitialized_copy(It first, It last, For dest)
{
using T = typename std::iterator_traits<For>::value_type;
for (; first != last; ++first, (void)++dest)
::new (static_cast<void*>(std::addressof(*dest))) T(*first);
}
This post addresses the following points from the perspective of the standard:
why ::new
is used instead of just new
;
why an explicit cast to void*
is required.
(This answer uses N4659, the final C++17 draft.)
::new
is used instead of just new
::new
ensures that the operator new
is looked up in the global scope. In contrast, the plain new
first looks up in the scope of the class if T
is a class type (or array thereof), and only then falls back to the global scope. Per [expr.new]/9 :
If the new-expression begins with a unary
::
operator, the allocation function's name is looked up in the global scope. Otherwise, if the allocated type is a class typeT
or array thereof, the allocation function's name is looked up in the scope ofT
. If this lookup fails to find the name, or if the allocated type is not a class type, the allocation function's name is looked up in the global scope.
For example, with
struct C {
void* operator new(std::size_t, void* ptr) noexcept
{
std::cout << "Hello placement new!\n";
return ptr;
}
};
The plain new
will cause this function to be found, thus printing unwanted message, whereas ::new
will still find the global function and work properly.
The global operator new(std::size_t, void*)
cannot be replaced because of [new.delete.placement]/1 :
These functions are reserved; a C++ program may not define functions that displace the versions in the C++ standard library ([constraints]). The provisions of [basic.stc.dynamic] do not apply to these reserved placement forms of
operator new
andoperator delete
.
(See How should I write ISO C++ Standard conformant custom new and delete operators? for more about overloading operator new
.)
void*
is required Although the global operator new(std::size_t, void*)
may not be replaced, new versions of ::operator new
can be defined. For example, suppose that the following declaration is placed in the global scope:
void* operator new(std::size_t, int* ptr) noexcept
{
std::cout << "Hello placement new!\n";
return ptr;
}
Then ::new(ptr) T
will use this version instead of the global version, where ptr
is a int*
value. The pointer is explicitly cast to void*
to ensure that the void*
version of operator new
(which we intend to call) wins in overload resolution.
From comment:
But why do we want to call exactly global
new
forvoid*
if some type has special overload of new for itself? Seems like normal overloaded operator is more suitable - why it's not?
Normally, new
is used for allocation purposes. Allocation is something the user should have control over. The user can roll out more suitable versions for a normal new
.
In this case, however, we don't want to allocate anything — all we want to do is create an object! The placement new is more of a "hack" — its presence is largely due to the lack of syntax available for constructing an object at a specified address. We don't want the user to be able to customize anything. The language itself, however, doesn't care about this hack, though — we have to treat it specially. Of course, if we have something like construct_at
(which is coming in C++20), we will use it!
Also note that std::uninitialized_copy
is intended for the simplest case where you just want to copy construct a sequence of objects in raw allocated space. The standard containers allow you to customize not only how the elements are allocated , but also how they are constructed , by means of an allocator. Therefore, they do not generally use std::uninitialized_copy
for their elements — they call std::allocator_traits<Allocator>::construct
. This feature is used by std::scoped_allocator_adaptor
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.