自C ++ 20起允许在分配的存储上使用指针算术吗?


10

在C ++ 20标准中,据说数组类型是隐式生存期类型

这是否意味着可以隐式创建非隐式生命周期类型的数组?这样的数组的隐式创建会不会导致创建数组的元素?

考虑这种情况:

//implicit creation of an array of std::string 
//but not the std::string elements:
void * ptr = operator new(sizeof (std::string) * 10);
//use launder to get a "pointer to object" (which object?)
std::string * sptr = std::launder(static_cast<std::string*>(ptr));
//pointer arithmetic on not created array elements well defined?
new (sptr+1) std::string("second element");

从C ++ 20开始,此代码不再是UB吗?


也许这种方法更好?

//implicit creation of an array of std::string 
//but not the std::string elements:
void * ptr = operator new(sizeof (std::string) * 10);
//use launder to get a "pointer to the array of 10 std::string" 
std::string (* sptr)[10] = std::launder(static_cast<std::string(*)[10]>(ptr));
//pointer arithmetic on an array is well defined
new (*sptr+1) std::string("second element");

1
我刚刚通过(草稿)C ++ 20标准进行了搜索,但没有发现将数组描述为“隐式生命周期类型”的任何内容(是的,我搜索了变体)。请提供您的索赔的更详细的说明(例如标准中的章节)。无法找到源,很难回答您的问题,更不用说任何相关的上下文了。
彼得·

1
@Peter:eel.is/c++draft/basic.types#9,最后一句话
Geza

我正在查看PDF open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4849.pdf(表面上是最新的工作草案),甚至连那句话都没有。看起来您也需要找到“隐式生命”的含义。我怀疑您的链接可能包含了一些“进行中的编辑”,这些编辑甚至还没有纳入已发布的工作草案中。
彼得

1
@Peter 所做的更改是最近的布拉格会议将P0593合并为标准的结果。他们尚未发布最终的草案,但是您可以在commit中看到合并的措词。
胡桃木

Answers:


3

这是否意味着可以隐式创建非隐式生命周期类型的数组?

是。

这样的数组的隐式创建会不会导致创建数组的元素?

是。

这就是使std::vector普通C ++实现的原因。


您是否还可以确认std::launder(static_cast<std::string*>(ptr))由于数组不在其生存期内而不返回指向数组第一个元素的指针,但由于数组在其生存期内而std::launder(static_cast<std::string(*)[10]>(ptr))返回指向数组的指针?
Oliv

对我来说这似乎是正确的。
TC

@Oliv而且我想std::launder实际上并不需要,因为eel.is/c++draft/intro.object#11确保ptr已经指向数组了?
核桃

@核桃,我错过了。所以一个static_caststd::string (*) [10]就足够了!发射
Oliv

@Oliv但是我想问题就变成了您的第一个没有的示例是否std::launder定义明确。没有std::string对象可以指向,但ptr可以指向数组,因此静态类型转换将使值保持不变,并且sptr也将指向数组。有了std::launderUB仅仅是因为std::launder的要求。
胡桃木
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.