以下代码的输出结果为:
void doit(const T1 &, const T2 &) [T1 = unsigned long, T2 = int]
t1 == t2
t1 == (T1)t2
t1 != (T1&)t2
t1 == (T1&&)t2
据我了解,t1 == t2
案例简直就是积分促销。
第二种情况t1 == (T1)t2
是同一件事,只是明确的。
第三种情况t1 == (T1&)t2
必须是一个reinterpret_cast
某种......不过,进一步的解释会有所帮助。
第四种情况t1 == (T1&&)t2
这就是我所坚持的。我在问题标题中添加了“临时物化”一词,因为这是我能得到的最接近的答案。
有人能帮我分析一下这四种情况吗?
Code:
#include <iostream>
template <typename T1, typename T2>
void doit(const T1& t1, const T2& t2) {
std::cout << __PRETTY_FUNCTION__ << '\n';
if (t1 == t2) {
std::cout << "t1 == t2" << '\n';
}
else {
std::cout << "t1 != t2" << '\n';
}
if (t1 == (T1)t2) {
std::cout << "t1 == (T1)t2" << '\n';
}
else {
std::cout << "t1 != (T1)t2" << '\n';
}
if (t1 == (T1&)t2) {
std::cout << "t1 == (T1&)t2" << '\n';
}
else {
std::cout << "t1 != (T1&)t2" << '\n';
}
if (t1 == (T1&&)t2) {
std::cout << "t1 == (T1&&)t2" << '\n';
}
else {
std::cout << "t1 != (T1&&)t2" << '\n';
}
}
int main() {
const unsigned long a = 1;
const int b = 1;
doit(a, b);
return 0;
}
编译器尝试按以下顺序将 c 样式转换解释为 c++ 样式转换(请参阅参考参数 http://en.cppreference.com/w/cpp/language/explicit_cast了解完整详情):
- 常量类型转换
- 静态类型转换
- static_cast 后跟 const_cast
- 重新解释_cast
- reinterpret_cast 后跟 const_cast
解读(T1)t2
非常简单。const_cast
失败了,但是static_cast
有效,所以它被解释为static_cast<T1>(t2)
(上面#2)。
For (T1&)t2
,不可能转换int&
to unsigned long&
via static_cast
. Both const_cast
and static_cast
失败,所以reinterpret_cast
最终被使用,给出reinterpret_cast<T1&>(t2)
。准确地说,上面#5,因为 t2 是 const:const_cast<T1&>(reinterpret_cast<const T1&>(t2))
.
编辑:static_cast
for (T1&)t2
由于关键行失败参考参数 http://en.cppreference.com/w/cpp/language/explicit_cast: “如果可以用多种方式将强制转换解释为 static_cast 后跟 const_cast,则无法对其进行编译。”。涉及隐式转换,并且以下所有内容都是有效的(我假设至少存在以下重载):
T1 c1 = t2; const_cast<T1&>(static_cast<const T1&>(c1))
const T1& c1 = t2; const_cast<T1&>(static_cast<const T1&>(c1))
T1&& c1 = t2; const_cast<T1&>(static_cast<const T1&>(std::move(c1)))
注意实际的表达,t1 == (T1&)t2
,导致未定义的行为,正如斯威夫特指出的那样(假设sizeof(int) != sizeof(unsigned long)
)。持有一个地址int
被视为(重新解释)为持有unsigned long
。交换定义的顺序a
and b
in main()
,结果将变为相等(在带有 gcc 的 x86 系统上)。这是唯一一个由于不好的原因而具有未定义行为的情况reinterpret_cast
。其他情况已明确定义,其结果是特定于平台的。
For (T1&&)t2
,转换来自int (lvalue)
to an unsigned long (xvalue)
. An xvalue
本质上是一个lvalue
那是“可移动的”;它不是一个参考。转换为static_cast<T1&&>(t2)
(上面#2)。转换相当于std::move((T1)t2)
, or std:move(static_cast<T1>(t2))
。编写代码时,使用std:move(static_cast<T1>(t2))
代替static_cast<T1&&>(t2)
,因为意图更加明确。
此示例说明为什么应使用 C++ 样式转换而不是 C 样式转换。 C++ 风格的转换的代码意图很明确,因为正确的转换是由开发人员明确指定的。对于 C 风格的强制转换,实际的强制转换由编译器选择,并且可能会导致令人惊讶的结果。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)