reinterpret_cast创建一个普通的默认可构造对象 [英] reinterpret_cast creating a trivially default-constructible object

查看:86
本文介绍了reinterpret_cast创建一个普通的默认可构造对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

cppreference 指出:

可以通过在任何适当对齐的存储上使用reinterpret_cast创建具有普通默认构造函数的

对象.在分配有std::malloc的内存上.

Objects with trivial default constructors can be created by using reinterpret_cast on any suitably aligned storage, e.g. on memory allocated with std::malloc.

这意味着以下是定义良好的代码:

This implies that the following is well-defined code:

struct X { int x; };
alignas(X) char buffer[sizeof(X)];    // (A)
reinterpret_cast<X*>(buffer)->x = 42; // (B)

接下来的三个问题:

  1. 那句话引用正确吗?
  2. 如果是,X的生命周期从什么时候开始?如果在行(B)上,是否将转换本身视为获取存储?如果在(A)行上,如果(A)(B)之间存在一个分支,该分支将有条件地构造一个X或某个其他容器Y?
  3. 在这方面C ++ 11和C ++ 1z之间有什么变化吗?
  1. Is that quote correct?
  2. If yes, at what point does the lifetime of the X begin? If on line (B), is it the cast itself that is considered acquiring storage? If on line (A), what if there were a branch between (A) and (B) that would conditionally construct an X or some other pod, Y?
  3. Does anything change between C++11 and C++1z in this regard?


请注意,这是一个旧链接.措词针对此问题进行了更改.现在显示为:


Note that this is an old link. The wording was changed in response to this question. It now reads:

但是,与C不同,不能通过简单地重新解释适当对齐的存储来创建具有琐碎默认构造函数的对象,例如,用std::malloc分配的内存:正式引入新对象并避免潜在的未定义行为时,需要placement-new.

Unlike in C, however, objects with trivial default constructors cannot be created by simply reinterpreting suitably aligned storage, such as memory allocated with std::malloc: placement-new is required to formally introduce a new object and avoid potential undefined behavior.

推荐答案

没有X对象,无论存在与否,因此假装存在一个会导致不确定的行为.

There is no X object, living or otherwise, so pretending that there is one results in undefined behavior.

[intro.object]/1 详尽地阐明了对象被创建:

[intro.object]/1 spells out exhaustively when objects are created:

对象由定义([basic.def]), new-expression ([expr.new]),当隐式更改活动 联合的成员([class.union]),或者当一个临时对象是 已创建([conv.rval],[class.temporary]).

An object is created by a definition ([basic.def]), by a new-expression ([expr.new]), when implicitly changing the active member of a union ([class.union]), or when a temporary object is created ([conv.rval], [class.temporary]).

随着 P0137R1 的采用,该段落是术语对象"的定义.

With the adoption of P0137R1, this paragraph is the definition of the term "object".

是否有X对象的定义?否.是否有 new-expression ?不,有工会吗?否.您的代码中是否存在可以创建临时X对象的语言构造?不.

Is there a definition of an X object? No. Is there a new-expression? No. Is there a union? No. Is there a language construct in your code that creates a temporary X object? No.

无论[basic.life]所说的带有空虚初始化的对象的生存期都是无关紧要的.为此,首先必须具有一个对象.你没有.

Whatever [basic.life] says about the lifetime of an object with vacuous initialization is irrelevant. For that to apply, you have to have an object in the first place. You don't.

C ++ 11具有大致相同的段落,但是没有将其用作对象"的定义.但是,解释是相同的.另一种解释-在获得适当的存储后将[basic.life]视为创建对象-意味着您正在创建Schrödinger的对象 * ,这与

C++11 has roughly the same paragraph, but doesn't use it as the definition of "object". Nonetheless, the interpretation is the same. The alternative interpretation - treating [basic.life] as creating an object as soon as suitable storage is obtained - means that you are creating Schrödinger's objects*, which contradicts N3337 [intro.object]/6:

如果一个对象不是位域,则两个对象可能具有相同的地址 是另一个的子对象,或者至少一个是基类 大小为零的子对象,它们是不同类型的;否则, 他们应该有不同的地址.

Two objects that are not bit-fields may have the same address if one is a subobject of the other, or if at least one is a base class subobject of zero size and they are of different types; otherwise, they shall have distinct addresses.


* 对于类型T,具有正确的对齐方式和大小的存储根据定义,对于具有其他大小的其他类型具有正确的对齐方式和大小的存储并且对齐要求等于或小于T的要求.因此,这种解释意味着获得存储空间同时在所述存储空间中创建了具有不同类型的无限对象集,所有对象都具有相同的地址.


* Storage with the proper alignment and size for a type T is by definition storage with the proper alignment and size for every other type whose size and alignment requirements are equal to or less than those of T. Thus, that interpretation means that obtaining the storage simultaneously creates an infinite set of objects with different types in said storage, all having the same address.

这篇关于reinterpret_cast创建一个普通的默认可构造对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆