如何让 C++11 汽车更智能?

how to make c++11 auto smarter?

本文关键字:智能 汽车 C++11      更新时间:2023-10-16

我现在开始在 c++ 11 中使用 auto 关键字。我发现它不那么聪明的一件事在下面的代码中说明:

unsigned int a = 7;
unsigned int b = 23;
auto c = a - b;
std::cout << c << std::endl;

如您所见,c变量的类型是无符号的 int。但我的意图是两个无符号 int 的区别应该是 int。所以我预计变量c等于 -16。 如何更明智地使用 auto,以便它可以将c变量的类型推断为 int?谢谢。

ab都有一种无符号的 int。因此,表达式的类型a - b被推导出为无符号 int,c具有无符号 int的类型。所以这里的自动工作是它应该做的。

如果要将类型从无符号int 更改为int,可以使用static_cast

auto c = static_cast<int>(a - b);

或者显式指定c的类型:

int c = a - b;

你误解了unsigned int类型是什么。

unsigned int是某些k(通常为 32)整数的模2^k。 减去两个这样的 mod-2^k整数是明确定义的,并且不是有符号整数。

如果需要对从-2^k2^k-1的有界整数集(k 通常等于 31)进行建模的类型,请使用int而不是unsigned int。 如果你想让他们是积极的,只需让他们成为积极的。

尽管它的名字,unsigned int并不是一个没有符号的int,因此是积极的。 相反,它是一种非常特殊的积分类型,碰巧没有符号的概念。

如果你不需要对一些定义的k未知实现进行mod-2^k数学运算,并且不需要将每个数量级的位打包到一个值中,请不要使用unsigned int

你似乎想要的是类似的东西

positive<int> a = 7;
positive<int> b = 23;
auto c = a-b; // c is of type `int`, because the difference of two positive values may be negative

通过一些语法更改和大量工作,这可能是可能的,但这不是unsigned的意思。

所以仅仅因为你不知道基本表达式是如何工作的,C++11 auto 关键字是愚蠢的吗?这对你来说有什么意义?

在表达式auto c = a - b;中,auto c =与子表达式a - b中使用的类型没有任何关系。

从第一个 C 语言草稿开始,表达式使用的类型就由该表达式的操作数决定。从试行标准的K&R C到C++17的所有内容都是如此。

现在,如果你想要负数,你需要做的是,毫不奇怪,使用负类型。在调用-运算符之前,将操作数更改为(带符号)int或将其强制转换为该类型。

将结果声明为有符号类型而不更改-的操作数类型不是一个好主意,因为这样会强制从无符号转换为有符号,这不一定是明确定义的行为。


现在,如果操作数具有不同的类型,或者属于小整数类型,则它们将按照通常的算术转换进行隐式提升。这不适用于此特定情况,因为两个操作数属于同一类型,而不是小整数类型。

但。。。这就是为什么auto关键字是愚蠢和危险的。考虑:

unsigned short a = 7;
unsigned short b = 23;
auto c = a - b;

由于两个操作数都是无符号的,程序员打算使用无符号算术。但在这里,两个操作数都被隐含地提升为int,符号发生了意外的变化。auto关键字假装什么都没发生,而unsigned int c = a - b;会增加编译器诊断消息的机会,或者至少增加外部静态分析工具发出警告的机会。而且它还会意外地消除原本可能是签名更改的错误。

此外,对于auto,我们最终会得到声明变量的错误、意外类型。