我发现在关键点附近使用“auto”可能会导致一些问题。
这是示例代码:
#include <iostream>
#include <typeinfo>
#include <limits>
using std::cout;
using std::endl;
using std::numeric_limits;
using std::cerr;
int main() {
auto i = 2147483647 /* numeric_limits<int>::max() */ ;
cout << "The type of i is " << typeid(i).name() << endl;
int count = 0;
for (auto i = 2147483647;
i < 2147483657 /* numeric_limits<int>::max() + 10 */ ; ++i) {
cout << "i = " << i << " " << endl;
if (count > 30) {
cerr << "Too many loops." << endl;
break;
}
++count;
}
return 0;
}
“auto”决定“i”的类型是整数,但整数的上限是2147483647,这很容易溢出。
这是Ideone(gcc-4.5.1)和LWS(gcc-4.7.2)上的输出。它们是不同的:“i”在Ideone(gcc-4.5.1)的循环中仍然是2147483647,在LWS(gcc-4.7.2)上溢出。但是没有一个是预期的结果:10个周期,每次+1。
我应该避免在关键点附近使用“自动”吗?或者我如何恰当地使用“自动”?
更新:有人说“在任何地方都可以自动使用”。在这个thread你告诉我。我不认为这是对的。类型“long long int”更适合这里的“int”类型。我想知道哪里可以安全地使用“自动”,哪里不能。
更新2:Herb Sutter的the article解决方案4(b)应该回答了这个问题。
答案 0 :(得分:0)
如果变量的类型正确,您应该只依靠类型推导来计算出变量的类型。在这里,编译器将其推断为int
,就标准而言正确,但是您的具体问题需要另一种具有更大范围的类型。当你使用auto
时,你会说“编译器最了解”,但编译器并不总是知道所有内容。
您不会在此使用auto
,就像您不使用int
一样。你可以让你的文字具有更高的等级(坚持L
或LL
之后 - 尽管它们不能保证比你的int
更大,然后auto
会推导出更大的整数类型。
更不用说auto
在这种情况下确实无法保存任何内容。 auto
通常用于避免键入您不知道的冗长,丑陋的类型或类型。在这种情况下,类型不长又丑,你知道它。
答案 1 :(得分:0)
auto
只是syntactic sugar。它不是一种类型,它只是推断出右侧应该是什么类型,并由此决定变量的类型。
如果给它文字,它只会推断出编译器给出的默认类型 您只需知道实际类型是什么。
答案 2 :(得分:0)
除非您明确更改其类型,否则数字文字(不带小数点)始终为int
。
int x = 2147483657; // 2147483657 is treated as an int.
// If it does not fit tough it will be truncated
// according to standard rules.
long x = 2147483657L; // The L suffix tells the compiler to treat it as a long.
// Here you will get the correct value assuming long is larger than int.
在你的情况下:
for(auto i = 2147483647;i < 2147483657;) // is not going to work as i is always
// an int and literal overflows.
// Try correct types:
for(auto i = 2147483647L; i < 2147483657L;++i) //Now it should work correctly.
答案 3 :(得分:0)
你期待auto
过多。您的期望是auto
会自动推断出类型,这种类型最适合您对变量 将要执行的操作。这是语义分析,编译器不希望这样做(大多数情况下,他们不能)。他们无法期待您将在程序中使用稍后声明的变量。
auto
关键字只会让您免于在左侧显式写入右侧出现的表达式类型的负担,避免可能的冗余以及与之相关的所有问题(如果表达式的类型如何,正确的变化?)
这就是说,所有其他答案都是正确的:如果您希望变量i
不溢出,则应为其分配long long
字面值(使用LL
后缀)。< / p>