【问题标题】:Is placement new legally required for putting an int into a char array?将 int 放入 char 数组中是否需要放置 new ?
【发布时间】:2017-01-12 23:08:12
【问题描述】:

由于 C++ 别名规则,您不能随意将 (一个 int*) 指向 char 数组,这似乎达成了一些共识。

从另一个问题——Generic char[] based storage and avoiding strict-aliasing related UB——看来,它似乎可以通过放置 new 来(重新)使用存储。

alignas(int) char buf[sizeof(int)];

void f() {
  // turn the memory into an int: (??) from the POV of the abstract machine!
  ::new (buf) int; // is this strictly required? (aside: it's obviously a no-op)

  // access storage:
  *((int*)buf) = 42; // for this discussion, just assume the cast itself yields the correct pointer value
}

那么,上面的 C++ 是否合法并且是真正需要的放置 new 以使其合法吗?

【问题讨论】:

  • 高度相关的潜在骗子:stackoverflow.com/questions/40873520/…
  • 建议更改标题的措辞,以明确您的意思是通过 int 左值访问 char 数组。您可以通过其他方式将 int 放入 char 数组中,例如memcpy 进进出出。
  • 在 C 中(在 C++ 中不确定)指向 char 的指针被排除在别名规则之外(即允许别名)。要反过来工作,您通常使用带有 int 和 char 成员的类型双关联。当然,剩下的问题是对齐,但我假设底层架构允许非对齐访问和/或指针正确对齐。

标签: c++ language-lawyer primitive-types strict-aliasing placement-new


【解决方案1】:

是的,new 的位置是必需的,否则你会违反严格的别名(分配是access)。

以上合法吗?几乎(尽管它几乎适用于所有实现)。您通过强制转换创建的指针不指向对象,因为(现在已销毁)数组和int 对象不是pointer-interconvertible;使用std::launder((int*)buf),或者更好的是,使用位置new 的返回值。

【讨论】:

  • reinterpret_cast<int&>(buf) = 42 没有违反严格的别名,因为它以int 类型的左值访问新的int 对象。 Pointer-interconvertible 适用于将一个“活动”指针转换为另一个,而不是将“死”指向非对象的指针转换为活动指针。编辑:我不确定那里是否需要launder;据我所知,规则仍在不断变化。
  • @Potatoswatter 哪个新的 int 对象?我说的是没有事先放置 new 来创建任何此类对象的情况。在重新解释指针时,我读到了通常适用的指针互转换性。无论如何,op 使用强制转换创建的指针并不指向 P0137 定义的新对象,因此launder 应该是必要的。
  • @Potatoswatter 我认为这不对。分配从不创建对象,除非分配给非活动的联合成员,不是吗?
  • @curiousguy 代码通过reinterpret_cast 获得一个指针(间接通过C 风格转换)。此指针仅在对应的指针是指针可互转换的情况下才有效,如引用段落所述。
  • @curiousguy 你的 cmets 看起来很天真。优化通过对语言施加某些限制(转化为优化器的假设)来工作。如果优化器有一组简单的规则来确定例程可以访问哪些对象,哪些不能,它可以执行alias optimizations
【解决方案2】:
*((int*)buf) = 42;

使用int 左值写入int,因此首先不存在别名问题。

【讨论】:

  • 首先没有别名问题。 ...除了静态存储中的原始数组成员肯定是char类型。允许您将(unsigned char*) 指向任何其他对象的字节的严格别名异常只会继续存在;将int* 指向绝对是char 的对象并不合法。 (如果这是匿名内存就好了,例如使用mmap 动态分配或返回void* 的东西,并且只能通过char*int* 访问。)
猜你喜欢
  • 2010-09-08
  • 2012-03-03
  • 2020-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多