将固定大小的数组的指针/引用转换为较小的大小是否合法 [英] Is it legal to convert a pointer/reference to a fixed array size to a smaller size

查看:72
本文介绍了将固定大小的数组的指针/引用转换为较小的大小是否合法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

按照C ++标准将指针或引用转换为固定数组是否合法(例如 T(*)[N] T(&)[N] )指向相同类型和CV限定条件(例如 T(*)[M] T(&)[M] )?

Is it legal as per the C++ standard to convert a pointer or reference to a fixed array (e.g. T(*)[N] or T(&)[N]) to a pointer or reference to a smaller fixed array of the same type and CV qualification (e.g. T(*)[M] or T(&)[M])?

基本上,对于 T 的所有实例化(无论布局类型如何),这始终应采用正确的格式:

Basically, would this always be well-formed for all instantiations of T (regardless of layout-type):

void consume(T(&array)[2]);

void receive(T(&array)[6])
{
  consume(reinterpret_cast<T(&)[2]>(array));   
}

在以下位置,我看不到任何对此进行有效转换的引用:

I don't see any references to this being a valid conversion in:

但是,即使使用 T = std :: string ( 根据我的理解,根据类型系统,这应该是非法的,因为从未真正创建 T [2] 的对象,这意味着引用了 T(&)[2] 无效.

It's my understanding that this should be illegal as per the type-system, since an object of T[2] was never truly created, which means a reference of T(&)[2] would be invalid.

我正在标记这个问题,因为这是我对答案最感兴趣的版本,但是我很想知道这个答案在较新的版本中是否有所不同.

I'm tagging this question c++11 because this is the version I am most interested in the answer for, but I would be curious to know whether this answer is different in newer versions a well.

推荐答案

在任何语言版本中,除了之外,这里没有什么要说的:类型完全无关.C ++ 20确实允许从 T(*)[N] 转换为 T(*)[] (以及类似的引用),但这并不意味着您可以等效地对待两个不同的 N .该规则最接近引用"的地方是[conv.array]/1(结果是指向数组第一个元素的指针.",它是 T [2] 在您的示例中不存在)和在[defns.undefined]中的 note (当本文档省略行为的任何明确定义时,可能会出现未定义的行为").

There’s not much to say here except no, in any language version: the types are simply unrelated. C++20 does allow conversion from T (*)[N] to T (*)[] (and similarly for references), but that doesn’t mean you can treat two different Ns equivalently. The closest you’re going to get to a "reference" for this rule is [conv.array]/1 ("The result is a pointer to the first element of the array.", which T[2] does not exist in your example) and a note in [defns.undefined] ("Undefined behavior may be expected when this document omits any explicit definition of behavior").

编译器不捕获"您的部分原因是这样的 reinterpret_cast 有效,可以返回为真实类型一个对象之后的另一个 reinterpret_cast 对象,该对象用于通过希望指针"或引用"为其他类型的接口隐藏"该对象(但不要使用作为该类型!).这意味着所给的代码是合法的,但是 consumption receive 的调用者的明显定义会一起导致未定义的行为.(另一部分是,优化器通常会留下总是未定义的代码,除非它可以消除分支.)

Part of the reason that compilers don’t "catch" you is that such reinterpret_casts are valid to return to the real type of an object after another reinterpret_cast used to "sneak" it through an interface that expects a pointer or reference to a different type (but doesn’t use it as that type!). That means that the code as given is legitimate, but the obvious sort of definition for consume and caller for receive would together cause undefined behavior. (The other part is that optimizers often leave code alone that’s always undefined unless it can eliminate a branch.)

这篇关于将固定大小的数组的指针/引用转换为较小的大小是否合法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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