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

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

更令人怀疑的是:

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

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

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


当前回答

一件容易的事。当你不关心是什么类型时使用它。例如

for (const auto & i : some_container) {
   ...

这里我只关心I是容器里的东西。

它有点像typedefs。

typedef float Height;
typedef double Weight;
//....
Height h;
Weight w;

这里,我不关心h和w是浮点数还是双精度浮点数,只关心它们是任何适合表示高度和权重的类型。

或者考虑

for (auto i = some_container .begin (); ...

这里我只关心它是一个合适的迭代器,支持运算符++(),在这方面有点像鸭子类型。

此外,lambdas的类型不能拼写,因此auto f =[]…是好的风格。另一种方法是强制转换为std::function,但这会带来开销。

我真的无法想象对汽车的“滥用”。我能想到的最接近的是剥夺你自己到一些重要类型的显式转换——但你不会使用auto,你会构造一个所需类型的对象。

如果您可以在不引入副作用的情况下删除代码中的一些冗余,那么这样做一定是好的。

反例(借用别人的回答):

auto i = SomeClass();
for (auto x = make_unsigned (y); ...)

这里我们确实关心类型是什么,所以我们应该写Someclass i;And for(unsigned x = y;…

其他回答

我指出的一个危险是在引用方面。 如。

MyBigObject& ref_to_big_object= big_object;
auto another_ref = ref_to_big_object; // ?

问题是,在这种情况下,another_ref实际上不是一个引用,它是MyBigObject而不是MyBigObject&。你最终复制了一个大对象而没有意识到它。

如果你直接从一个方法中得到一个引用,你可能不会考虑它实际上是什么。

auto another_ref = function_returning_ref_to_big_object();

你需要"auto&"或者"const auto&"

MyBigObject& ref_to_big_object= big_object;
auto& another_ref = ref_to_big_object;
const auto& yet_another_ref = function_returning_ref_to_big_object();

我认为,当第一眼就不知道如何写类型,但表达式右边的类型很明显时,应该使用auto关键字。例如,使用:

my_multi_type::nth_index<2>::type::key_type::composite_key_type::
    key_extractor_tuple::tail_type::head_type::result_type

要在boost::multi_index中获取复合键类型,即使您知道它是int。你不能只写int,因为它将来可能会被改变。在这种情况下我会写auto。

因此,如果auto关键字在特定情况下提高了可读性,那么就使用它。当读者很清楚auto所代表的类型时,可以使用auto。

下面是一些例子:

auto foo = std::make_shared<Foo>();   // obvious
auto foo = bla();                     // unclear. don't know which type `foo` has

const size_t max_size = 100;
for ( auto x = max_size; x > 0; --x ) // unclear. could lead to the errors
                                      // since max_size is unsigned

std::vector<some_class> v;
for ( auto it = v.begin(); it != v.end(); ++it )
                                      // ok, since I know that `it` has an iterator type
                                      // (don't really care which one in this context)

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

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

这只是我的观点。

大胆尝试吧。在任何地方使用auto可以使编写代码更容易。

任何语言中的每一个新特性都会被至少某些类型的程序员过度使用。只有通过一些有经验的程序员(不是新手)适度的过度使用,其他有经验的程序员才能学会正确使用的界限。过度使用通常是不好的,但也可能是好的,因为这种过度使用可能会导致功能的改进或更好的功能来取代它。

但如果我写的代码不止几行,比如

auto foo = bla();

where the type is indicated zero times, I might want to change those lines to include types. The first example is great since the type is stated once, and auto saves us from having to write messy templated types twice. Hooray for C++++. But explicitly showing the type zero times, if it's not easily visible in a nearby line, makes me nervous, at least in C++ and its immediate successors. For other languages designed to work at a higher level with more abstraction, polymorphism and genericity, it's fine.