c++ - 为什么 C++17 中没有 std::construct_at ?
问题描述
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)...);
}
这将能够避免这种不完全自然的放置新语法:
auto ptr = construct_at<int>(buf, 1); // instead of 'auto ptr = new (buf) int(1);'
std::cout << *ptr;
std::destroy_at(ptr);
解决方案
std::destroy_at
与直接析构函数调用相比,提供了两个客观的改进:
它减少了冗余:
T *ptr = new T; //Insert 1000 lines of code here. ptr->~T(); //What type was that again?
当然,我们都更愿意将它包装在 a 中
unique_ptr
并完成它,但如果由于某种原因不能做到这一点,那么就T
存在冗余元素。如果我们将类型更改为U
,我们现在必须更改析构函数调用,否则会中断。使用std::destroy_at(ptr)
消除了在两个地方更改相同内容的需要。干是好的。
它使这很容易:
auto ptr = allocates_an_object(...); //Insert code here ptr->~???; //What type is that again?
如果我们推断出指针的类型,那么删除它就变得有点困难了。你不能这样做
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();
谁想打字?
相比之下,您的假设std::construct_at
没有提供比放置的客观new
改进。在这两种情况下,您都必须说明您正在创建的类型。在这两种情况下都必须提供构造函数的参数。在这两种情况下都必须提供指向内存的指针。
所以没有必要被你的假设解决std::construct_at
。
它在客观上不如安置新。你可以这样做:
auto ptr1 = new(mem1) T;
auto ptr2 = new(mem2) T{};
这些是不同的。在第一种情况下,对象是默认初始化的,这可能会使其未初始化。在第二种情况下,对象是值初始化的。
你的假设std::construct_at
不能让你选择你想要的。如果您不提供任何参数,它可以具有执行默认初始化的代码,但是它将无法提供用于值初始化的版本。它可以在没有参数的情况下初始化值,但是你不能默认初始化对象。
请注意,C++20 添加了std::construct_at
. 但它这样做是出于一致性以外的原因。它们在那里支持编译时内存分配和构造。
您可以在常量表达式中调用“可替换”全局new
运算符(只要您实际上没有替换它)。但是placement-new 不是一个“可替换”的函数,所以你不能在那里调用它。
constexpr 分配提案的早期版本依赖于std::allocator_traits<std::allocator<T>>::construct/destruct
. 他们后来转移到std::construct_at
作为constexpr
构造函数,这construct
将是指。
construct_at
当可以提供对placement-new 的客观改进时,添加了So。
推荐阅读
- windows - Kotlin JS Client 和 JVM Server 构建 webpack SyntaxError
- javascript - 创建一个简单的多维对象数组并分配给 cookie
- cakephp - CakePHP crontab intl
- c# - Console doesn't write any value
- wikipedia - 维基媒体图片说明
- excel - 通过数组模拟 AdvancedFilter CriteriaRange 对象
- python - 在 Alpine Edge 中安装 py[2]-numpy(Alpine 3.10 是最新的并且具有 py[2]-numpy)
- python - 如何为 tf.layers.Conv3D 提供输入层?
- javascript - nested mongodb queries in a loop
- r - Comparing character dates across columns in R