我现在开始在c ++ 11中使用auto关键字。我发现它不那么聪明的一件事在下面的代码中说明:
unsigned int a = 7;
unsigned int b = 23;
auto c = a - b;
std::cout << c << std::endl;
如您所见,c
变量的类型是unsigned int。但我的意图是两个unsigned int的区别应该是int。所以我希望变量c
等于-16。我怎样才能更明智地使用auto,以便它可以将c
变量的类型推断为int?谢谢。
答案 0 :(得分:6)
a
和b
都有 unsigned int 的类型。因此,表达式a - b
的类型推断为 unsigned int ,c
的类型为 unsigned int 。所以 auto 就像它应该的那样工作。
如果要将类型从 unsigned int 更改为 int ,可以使用 static_cast :
auto c = static_cast<int>(a - b);
或明确指定c
的类型:
int c = a - b;
答案 1 :(得分:1)
你误解了unsigned int
类型是什么。
unsigned int
是一个mod - 2^k
,用于某些k
(通常为32)整数。减去两个这样的mod - 2^k
整数是明确定义的,并且不是有符号整数。
如果您想要一种模型从-2^k
到2^k-1
(k通常等于31)的有界整数集的模型,请使用int
代替unsigned int
。如果你想让他们变得积极,那就让他们变得积极。
尽管名称如此,unsigned int
不是int
,但没有任何迹象,因此是正面的。相反,它是一种非常具体的整体类型,恰好没有符号概念。
如果你不需要mod-2^k
数学用于某个未知的实现定义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
的含义。
答案 2 :(得分:1)
因为你不知道基本表达式是如何工作的,所以C ++ 11 auto关键字是愚蠢的吗?这怎么对你有意义?
在表达式auto c = a - b;
中,auto c =
与子表达式a - b
中使用的类型无关。
自从第一个C语言草稿以来,表达式使用的类型由该表达式的操作数决定。对于从预标准K&amp; R C到C ++ 17的所有内容都是如此。
现在,如果你想要负数,你需要做的就是使用负面类型,这并不奇怪。在调用int
运算符之前,将操作数更改为(signed)-
或将它们转换为该类型。
将结果声明为有符号类型而不更改-
操作数的类型并不是一个好主意,因为这会强制从无符号转换为有符号,这不一定是明确定义的行为。
现在,如果操作数具有不同的类型,或者是小整数类型,则它们将按照通常的算术转换进行隐式提升。这不适用于这种特定情况,因为两个操作数是相同类型而不是小整数类型。
但是...... 这个是auto
关键字愚蠢和危险的原因。考虑:
unsigned short a = 7;
unsigned short b = 23;
auto c = a - b;
由于两个操作数都是无符号的,程序员打算使用无符号算术。但是这里两个操作数都被隐式提升为int
,意外改变了签名。 auto
关键字假装没有发生任何事情,而unsigned int c = a - b;
会增加编译器诊断消息的机会,或者至少增加外部静态分析工具发出警告的可能性。而且它也会意外地平滑掉原本可能会发生变更的错误。
此外,对于auto
,我们最终会为声明的变量设置错误的,无意的类型。