Dan*_*ica 58 c++ placement-new c++17
C++ 17补充说std::destroy_at
,但没有任何std::construct_at
对应物.这是为什么?难道不能像下面这样简单地实现吗?
template <typename T, typename... Args>
T* construct_at(void* addr, Args&&... args) {
return new (addr) T(std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)
这样可以避免不完全自然的放置新语法:
auto ptr = construct_at<int>(buf, 1); // instead of 'auto ptr = new (buf) int(1);'
std::cout << *ptr;
std::destroy_at(ptr);
Run Code Online (Sandbox Code Playgroud)
Nic*_*las 40
std::destroy_at
对直接析构函数调用提供了两个客观的改进:
它减少了冗余:
T *ptr = new T;
//Insert 1000 lines of code here.
ptr->~T(); //What type was that again?
Run Code Online (Sandbox Code Playgroud)
当然,我们都希望将它包装成一个unique_ptr
并完成它,但如果由于某种原因不能发生,那么放置T
一个冗余元素.如果我们将类型更改为U
,我们现在必须更改析构函数调用或事务中断.使用std::destroy_at(ptr)
无需在两个地方更改相同的内容.
干很好.
它使这很容易:
auto ptr = allocates_an_object(...);
//Insert code here
ptr->~???; //What type is that again?
Run Code Online (Sandbox Code Playgroud)
如果我们推断出指针的类型,那么删除它会变得很难.你做不到ptr->~decltype(ptr)()
; 因为C++解析器不能以这种方式工作.不仅如此,decltype
将类型推断为指针,因此您需要从推导类型中删除指针间接.引导您:
auto ptr = allocates_an_object(...);
//Insert code here
using delete_type = std::remove_pointer_t<decltype(ptr)>;
ptr->~delete_type();
Run Code Online (Sandbox Code Playgroud)
和谁愿意键入那?
相比之下,您的假设std::construct_at
没有提供关于放置的客观改进new
.您必须在两种情况下都说明您正在创建的类型.在两种情况下都必须提供构造函数的参数.在两种情况下都必须提供指向存储器的指针.
所以你的假设不需要解决std::construct_at
.
并且客观上不如放置新的能力.你可以这样做:
auto ptr1 = new(mem1) T;
auto ptr2 = new(mem2) T{};
Run Code Online (Sandbox Code Playgroud)
这些是不同的.在第一种情况下,对象是默认初始化的,这可能会使其未初始化.在第二种情况下,对象是值初始化的.
假想的std::construct_at
不能让你选择你想要哪一个.如果您不提供参数,它可以具有执行默认初始化的代码,但是它将无法提供值初始化的版本.并且它可以在没有参数的情况下初始化值,但是您无法默认初始化对象.
Mar*_*k R 13
有这样的事情,但没有像你期望的那样命名:
uninitialized_copy 将一系列对象复制到未初始化的内存区域
uninitialized_copy_n (C++ 11)将许多对象复制到未初始化的内存区域(函数模板)
uninitialized_fill 将对象复制到未初始化的内存区域,由范围(函数模板)定义
小智 9
有std::allocator_traits::construct
.标准委员会文件D0174R0中曾经有过一次std::allocator
,但已被删除.
std::construct_at
已添加到C ++ 20。这样做的文件是More constexpr容器。据推测,与C ++ 17中的新增功能相比,这没有看到足够的优势,但是C ++ 20改变了一切。
建议添加此功能的目的是为了支持constexpr内存分配,包括std::vector
。这要求能够将对象构造到分配的存储中。然而,在以下方面只是简单的放置新的交易void *
,不是T *
。 constexpr
评价目前无法访问原始存储,委员会希望保持这种状态。库函数std::construct_at
添加了一个类型化的接口constexpr T * construct_at(T *, Args && ...)
。
这还具有不需要用户指定正在构造的类型的优点。它是根据指针的类型推导出来的。正确地将放置位置称为“ new”的语法有点可怕且违反直觉。std::construct_at(ptr, args...)
与比较::new(static_cast<void *>(ptr)) std::decay_t<decltype(*ptr)>(args...)
。
归档时间: |
|
查看次数: |
3055 次 |
最近记录: |