我一直在使用c++ 11标准中提供的新的auto关键字来处理复杂的模板类型,我相信它就是为这个目的设计的。但我也用它来做以下事情:
auto foo = std::make_shared<Foo>();
更令人怀疑的是:
auto foo = bla(); // where bla() return a shared_ptr<Foo>
我还没有看到很多关于这个话题的讨论。auto似乎被滥用了,因为类型通常是一种文档和完整性检查的形式。你在使用auto方面的界限在哪里,这个新功能的推荐用例是什么?
澄清一下:我并不是在寻求哲学观点;我要求标准委员会对这个关键字的预期使用,可能还会对如何在实践中实现预期使用发表评论。
auto与线性代数库(如Eigen或OpenCV)大量使用的表达式模板结合使用可能非常危险。
auto A = Matrix(...);
auto B = Matrix(...);
auto C = A * B; // C is not a matrix. It is a matrix EXPRESSION.
cout << C; // The expression is evaluated and gives the expected result.
... // <code modifying A or B>
cout << C; // The expression is evaluated AGAIN and gives a DIFFERENT result.
由这类错误引起的bug是调试的一大麻烦。一种可能的补救方法是,如果执意要将auto用于从左到右的声明样式,则显式地将结果转换为预期的类型。
auto C = Matrix(A * B); // The expression is now evaluated immediately.
TL;DR:见底部的经验法则。
公认的答案包含以下经验法则:
当第一眼不知道如何写类型,但表达式右边的类型很明显时,请使用auto。
但我想说这太严格了。有时我并不关心类型,因为语句已经提供了足够的信息,而无需我花时间去弄清楚类型。这是什么意思呢?考虑一下一些答案中出现的例子:
auto x = f();
是什么使这个例子滥用auto?是我不知道f()的返回类型吗?好吧,如果我知道的话可能会有帮助,但是-这不是我主要关心的。更大的问题是x和f()是没有意义的。如果我们有:
auto nugget = mine_gold();
相反,我通常不关心函数的返回类型是否明显。读这个语句,我知道我在做什么,我对返回值的语义有足够的了解,所以我不觉得我还需要知道它的类型。
所以我的回答是:只要编译器允许,就使用auto,除非:
You feel the variable name together with the initialization / assignment expression do not provide enough information about what the statement is doing.
You feel the variable name together with the initialization / assignment expression provides "misleading" information about what the type should be - i.e., if you had to guess what comes instead of the auto you would be able to make a guess - and it would be wrong, and this false assumption has repercussions later in the code.
You want to force a different type (e.g. a reference).
还有:
在用具体类型替换auto之前,最好给出一个有意义的名称(当然不包含类型名)。
auto与线性代数库(如Eigen或OpenCV)大量使用的表达式模板结合使用可能非常危险。
auto A = Matrix(...);
auto B = Matrix(...);
auto C = A * B; // C is not a matrix. It is a matrix EXPRESSION.
cout << C; // The expression is evaluated and gives the expected result.
... // <code modifying A or B>
cout << C; // The expression is evaluated AGAIN and gives a DIFFERENT result.
由这类错误引起的bug是调试的一大麻烦。一种可能的补救方法是,如果执意要将auto用于从左到右的声明样式,则显式地将结果转换为预期的类型。
auto C = Matrix(A * B); // The expression is now evaluated immediately.
我使用auto的一个痛苦经历是在lambda表达式中使用它:
auto i = []() { return 0; };
cout<<"i = "<<i<<endl; // output: 1 !!!
实际上,这里i被解析为int(*)()的函数指针。这只是一个简单的cout,但是想象一下,当它与template一起使用时,会导致什么样的编译/运行时错误。
你应该避免使用这样的表达式,并设置一个合适的返回类型(或受控的decltype())
上述例子的正确用法是:
auto i = []() { return 0; }(); // and now i contains the result of calling the lambda