我一直在使用c++ 11标准中提供的新的auto关键字来处理复杂的模板类型,我相信它就是为这个目的设计的。但我也用它来做以下事情:

auto foo = std::make_shared<Foo>();

更令人怀疑的是:

auto foo = bla(); // where bla() return a shared_ptr<Foo>

我还没有看到很多关于这个话题的讨论。auto似乎被滥用了,因为类型通常是一种文档和完整性检查的形式。你在使用auto方面的界限在哪里,这个新功能的推荐用例是什么?

澄清一下:我并不是在寻求哲学观点;我要求标准委员会对这个关键字的预期使用,可能还会对如何在实践中实现预期使用发表评论。


当前回答

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之前,最好给出一个有意义的名称(当然不包含类型名)。

其他回答

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关键字只能用于局部变量,不能用于参数或类/结构成员。所以,在任何你喜欢的地方使用它们都是安全可行的。我确实经常使用它们。类型在编译时推导,调试器在调试时显示类型,sizeof正确报告它,decltype将给出正确的类型——没有伤害。我从不认为auto是过度使用的!

在推断类型有意义的地方使用auto。如果你知道它是一个整数,或者你知道它是一个字符串,只需使用int / std::string等。我不担心“过度使用”一种语言特性,除非它达到荒谬的地步,或者混淆代码。

这只是我的观点。

在任何可能的地方都使用auto -特别是const auto,这样副作用就不那么重要了。除了一些明显的情况外,您不必担心类型,但它们仍然会为您进行静态验证,并且可以避免一些重复。在auto不可行的地方,可以使用decltype将类型语义地表示为基于表达式的契约。您的代码看起来会有所不同,但这将是一个积极的变化。

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.