自 C++20 以来,是否允许对分配的存储进行指针运算?
Is pointer arithmetic on allocated storage allowed since 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回答+评论结论:
- 没有创建数组元素,但是创建了数组
- 在第一个示例中使用
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");
Does it means that an array to a non implicit lifetime type can be implicitly created?
是的。
The implicit creation of such an array would not cause creation of the array's elements?
是的。
这就是 std::vector
可以在普通 C++ 中实现的原因。
在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回答+评论结论:
- 没有创建数组元素,但是创建了数组
- 在第一个示例中使用
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");
Does it means that an array to a non implicit lifetime type can be implicitly created?
是的。
The implicit creation of such an array would not cause creation of the array's elements?
是的。
这就是 std::vector
可以在普通 C++ 中实现的原因。