初始化数组,放置新,读取变量,定义的行为

initialize array, placement new, read variables, defined behavior?

本文关键字:定义 变量 数组 初始化 读取      更新时间:2023-10-16

给定一个类,它的唯一成员是一个char[10],它没有继承也没有虚拟成员,它有一个构造函数不以任何方式提及数组(这样它得到默认初始化 ->没有初始化,如下所示:

class in_place_string {
    char data[10];
    static struct pre_initialized_type {} pre_initialized;
    in_place_string(pre_initialized_type) {}  //This is the constructor in question
    in_place_string() :data() {} //this is so you don't yell at me, not relevent
};

是否定义了将此类新放置到已有数据的缓冲区中,然后从数组成员中读取的行为?

int main() {
    char buffer[sizeof(in_place_string)] = "HI!";
    in_place_string* str = new(buffer) in_place_string(in_place_string::pre_initialized);
    cout << str->data; //undefined behavior?
}

我很确定它没有很好地定义,所以我问这是实现定义还是未定义的行为。

您没有执行reinterpret_cast(这不安全,因为该类具有非平凡的初始化(;您正在创建一个成员未初始化的新对象。

对未初始化的对象执行左值>rvalue转换会给出不确定的值和未定义的行为。 那么对象是未初始化的吗?

根据 5.3.4,new-expression 创建的所有对象都具有动态存储持续时间。 新版位也不例外。

由新表达式创建的实体具有动态存储持续时间

然后 8.5 说

如果未为对象指定初始值设定项,则默认初始化该对象。 当获取具有自动或动态存储持续时间的对象的存储时,该对象具有不确定值,如果未对对象执行初始化,则该对象将保留不确定值,直到该值被替换 (5.17(。 [注意:具有静态或线程存储持续时间的对象初始化为零,请参阅尾注]如果计算生成不确定的值,则除以下情况外,未定义行为:

以下情况只允许unsigned char,即使这样,该值也没有用。

在您的情况下,新对象具有动态存储持续时间 (!(,并且未对其执行初始化的成员具有不确定的值。 阅读它们会产生未定义的行为。

我认为相关条款是8.5 [dcl.init]第12段:

如果未为对象指定初始值设定项,则默认初始化该对象。当获取具有自动或动态存储持续时间的对象的存储时,该对象具有不确定值,如果未对对象执行初始化,则该对象将保留不确定值,直到该值被替换 (5.17(。[ 注意:具有静态或线程存储持续时间的对象初始化为零,请参阅 3.6.2。如果评估生成了不确定的值,则行为是未定义的,除非在 以下情况:

  • 如果通过计算以下各项产生无符号窄字符类型 (3.9.1( 的不确定值:
    • 条件表达式的第二个或第三个操作数 (5.16(,
    • 逗号表达式的右操作数 (5.18(,
    • 转换为无符号窄字符类型(4.7、5.2.3、5.2.9、5.4(的操作数,或
    • 一个丢弃值表达式(子句 5(,则操作的结果是不确定值。
  • 如果无符号窄字符类型的不确定值是通过计算简单赋值运算符 (5.17( 的右操作数生成的,该运算符的第一个操作数是无符号窄字符类型的左值,则不确定值将替换左操作数引用的对象的值。
  • 如果在初始化无符号窄字符类型的对象时,初始化表达式的计算生成了无符号窄字符类型的不确定值,则该对象将初始化为不确定值。

我认为任何例外都不适用。由于在构造对象后初始化之前会读取该值,因此我认为代码会导致未定义的行为。