Sup*_*sor 11 c++ language-lawyer c++11
下面代码的输出产生:
void doit(const T1 &, const T2 &) [T1 = unsigned long, T2 = int]
t1 == t2
t1 == (T1)t2
t1 != (T1&)t2
t1 == (T1&&)t2
Run Code Online (Sandbox Code Playgroud)
我知道这个t1 == t2案子只是一个不可或缺的促销活动.
第二种情况t1 == (T1)t2是相同的,只是明确的.
第三种情况t1 == (T1&)t2必须是reinterpret_cast某种形式......但是,进一步的解释会有所帮助.
第四种情况t1 == (T1&&)t2是我坚持的.我在问题的标题中加入了"临时实现"这个术语,因为这是我能得到某种答案的最接近的.
有人可以查看这四个案例吗?
码:
#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;
}
Run Code Online (Sandbox Code Playgroud)
Swi*_*Pie -2
从技术上讲,所有四种变体都依赖于平台
t1 == t2
t2 被提升为 'long',转换为unsigned long.
t1 == (T1)t2
signed int被转换为其表示形式为unsigned long,以便被强制转换为long第一个。对于是否必须将其视为 UB 存在争议,因为结果取决于平台,老实说,除了 C99 标准中的条款之外,我真的不确定现在如何定义它。比较结果将与 相同t1 == t2。
t1 == (T1&)t2
转换结果是一个引用,您将引用(本质上是一个指针)与 T1 进行比较,该操作会产生未知的结果。为什么?引用 js 指向不同的类型。
t1 == (T1&&)t2
转换表达式产生一个右值,因此您可以比较值,但其类型是右值引用。比较结果将与 相同t1 == t2。
附言。如果你使用这样的值,就会发生有趣的事情(取决于平台,本质上是 UB):
const unsigned long a = 0xFFFFFFFFFFFFFFFF;
const int b = -1;
Run Code Online (Sandbox Code Playgroud)
输出可能是:
t1 == t2
t1 == (T1)t2
t1 == (T1&)t2
t1 == (T1&&)t2
Run Code Online (Sandbox Code Playgroud)
这就是为什么在比较无符号和有符号值时应小心的原因之一,尤其是使用 < 或 > 时。您会对 -1 大于 1 感到惊讶。
ifunsigned long是 64 位 int 并且指针等于 64 位 int。-1 如果转换为无符号,则成为其二进制表示形式。本质上,b 将成为地址为 0xFFFFFFFFFFFFFFFF 的指针。
| 归档时间: |
|
| 查看次数: |
502 次 |
| 最近记录: |