根据 C++ 标准,将指针或引用转换为固定数组(例如T(*)[N]
or T(&)[N]
)指向相同类型和 CV 限定的较小固定数组的指针或引用(例如T(*)[M]
or T(&)[M]
)?
基本上,对于所有实例来说,这总是格式良好吗T
(无论布局类型如何):
void consume(T(&array)[2]);
void receive(T(&array)[6])
{
consume(reinterpret_cast<T(&)[2]>(array));
}
我在以下位置没有看到任何对此有效转换的引用:
-
expr.reinterpret.cast https://timsong-cpp.github.io/cppwp/n3337/expr.reinterpret.cast,
-
expr.static.cast https://timsong-cpp.github.io/cppwp/n3337/expr.static.cast,
-
conv.array https://timsong-cpp.github.io/cppwp/n3337/conv.array, 甚至
- basic.types https://timsong-cpp.github.io/cppwp/n3337/basic.types
However, it appears that all major compilers accept this and generate proper code even when optimized when using T = std::string
(compiler explorer https://gcc.godbolt.org/z/TW7dPW)(not that this proves much, if it is undefined behavior).
据我了解,根据类型系统,这应该是非法的,因为T[2]
从未真正创建过,这意味着引用T(&)[2]
将无效。
我正在标记这个问题c++11 /questions/tagged/c%2b%2b11因为这是我对答案最感兴趣的版本,但我很想知道这个答案在新版本中是否有所不同。
这里没什么好说的,除了no,在任何语言版本中:类型完全不相关。 C++20 确实允许从T (*)[N]
to T (*)[]
(参考文献也类似),但这并不意味着你可以对待两种不同的N
s 等价。您最接近此规则的“引用”是 [conv.array]/1(“结果是指向数组第一个元素的指针。”,其中T[2]
您的示例中不存在)和note在 [defns.undefined] 中(“当本文档省略任何明确的行为定义时,可能会出现未定义的行为”)。
编译器没有“抓住”你的部分原因是这样的reinterpret_cast
s are有效return到一个又一个对象的真实类型reinterpret_cast
用于通过需要指针或对不同类型的引用的接口“偷偷”它(但不use它就是那种类型!)。这意味着给出的代码是合法的,但是明显的定义consume
和来电者receive
would together导致未定义的行为。 (另一部分是优化器经常不理会代码,那就是always未定义,除非它可以消除分支。)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)