首页 > 解决方案 > 自 C++20 以来是否允许对分配的存储进行指针运算?

问题描述

在 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 object" (actually not necessary)
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");

TC 答案 + 评论结论:

  1. 未创建数组元素,但已创建数组
  2. 在第一个示例中使用launder导致 UB,在第二个示例中没有必要。

正确的代码是:

    //implicit creation of an array of std::string 
    //but not the std::string elements:
    void * ptr = operator new(sizeof (std::string) * 10);
    //the pointer already points to the implicitly created object
    //so casting is enough 
    std::string (* sptr)[10] = static_cast<std::string(*)[10]>(ptr);
    //pointer arithmetic on an array is well defined
    new (*sptr+1) std::string("second element");

标签: c++arraysdynamic-arrayslifetimec++20

解决方案


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

是的。

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

是的。

这就是std::vector在普通 C++ 中可以实现的原因。


推荐阅读