我很高兴在我的C ++程序中使用auto
变量。我知道使用auto
声明的变量使用模板规则来推导变量类型,但我对数字类型的工作原理感到困惑。假设我有:
auto foo = 12;
foo
的类型可以合理地是int
甚至unsigned char
。但是假设在我的程序中稍后我会做一些数学并给foo赋值40亿。在那一点上,我希望foo
成为unsigned int
类型或者long
。
编译器如何预测将在程序中稍后分配的值?
编译器使用存在的信息,在您的情况下是整数文字12
。所以它推断出foo
是int
类型。它没有任何预期。您可以使用适当的integer literal后缀:
auto foo = 12ul;
迫使foo
被推断为unsigned long
。您无法将变量定义为int
类型,然后在该行下方期望编译器以某种方式将其更改为另一种类型,因为您分配了一个不适合以前使用的类型的不同值。如果你这样做,它只会导致整数溢出,这是未定义的行为。
有关该主题的更多信息,请查看auto specifier和auto type deduction参考。
“foo的类型可以合理地为int或甚至unsigned char”
不,它不能。 C ++中的每个表达式都有一个类型,并且在语言中明确定义。在您的情况下,表达式是整数文字,因此类型对应于文字。具体是什么类型,由rules定义:
文字的类型
整数文字的类型是值可以适合的第一种类型,从类型列表中取决于使用哪个数字基数和哪个整数后缀。
无后缀 - int,long int,long long int(自C ++ 11起)
“编译器如何预测将在程序后期分配的值?”
这不可以。声明变量时确定类型,以后不能更改。
foo的类型可以合理地为int或甚至unsigned char
它可能是很多东西,但它实际上只是一件事。
整数文字12
的类型为int
。
期。
但是假设后来在我的程序中,我做了一些数学运算并给foo赋值40亿。那时,我希望foo有类型unsigned int或者long。编译器如何预测将在程序中稍后分配的值?
他们不能,他们不能。 foo
的类型不会改变。 foo
没有类型auto
(没有这样的东西);它有类型int
。你今后的计划就好像你写了int foo = 12;
。演绎/自动化在那里结束。
那时,我希望
foo
有类型unsigned int
或者long
。
这不是语言的工作方式。变量不能在运行时更改其类型。如果您将变量定义并初始化为auto foo = 12;
,那意味着与int foo = 12;
完全相同,无论将来的任何分配如何,因为12
的类型是int
。
编译器如何预测将在程序中稍后分配的值?
他们不必。稍后分配的值将转换为变量的类型。如果该值超出该类型的范围,则确切的规则取决于您正在处理的类型。
我的建议是,这不是一个使用auto
的好地方。您知道哪些因素决定了您需要的类型,并且无法从直接上下文中推断出它们。 (但是,如果您可以将变量编写为单个静态赋值,则不会发生这种情况。)
如果您知道变量需要能够保存至少40亿的值,请将其声明为unsigned long
或long long int
。或者,如果您真的想要针对这些类型的宽度(例如long
为32位宽以支持遗留代码,但本机字大小为64位的平台)进行防御性编码,请将其声明为uint_fast32_t
或int_fast64_t
。或者如果你想要最小的,而不是最快的uint_least32_t
。 (有时,最快的代码是在缓存中保留最多值的代码!)
如果你真正想要的是最快的签名或无符号类型,可以保持40亿的价值,说出你的意思!
就个人而言,我不会对这些直接常量使用auto,但是值来自另一个方法调用,或者从另一个变量赋值。
如果你想要一种方法来定义一个变量以匹配另一个变量的类型,那么你可以与它进行互操作,但是你想要分配一个常量值,然后使用decltype来确保它的大小是兼容的:
decltype(otherVar) myVar = 1234;
myVar += otherVar; // will work just as well as otherVar += myVar
在任何情况下,类型由文字常量指定,未修饰的12将定义int。
但是,您可以使用U来装饰常量,使其无符号,或者使L变长,或者使LL变长,以使其超长。不幸的是,没有相当于强迫它短或char!