C ++ 11 auto 关键字太多了?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6434971/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:07:00  来源:igfitidea点击:

How much is too much with C++11 auto keyword?

c++typesc++11type-inferenceauto

提问by Alan Turing

I've been using the new autokeyword available in the C++11 standard for complicated templated types which is what I believe it was designed for. But I'm also using it for things like:

我一直在使用autoC++11 标准中可用的 new关键字来处理复杂的模板化类型,我相信它就是为此而设计的。但我也将它用于以下方面:

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

And more skeptically for:

更怀疑的是:

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

I haven't seen much discussion on this topic. It seems that autocould be overused, since a type is often a form of documentation and sanity checks. Where do you draw the line in using autoand what are the recommended use cases for this new feature?

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

To clarify: I'm not asking for a philosophical opinion; I'm asking for the intended use of this keyword by the standard committee, possibly with comments on how that intended use is realized in practice.

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

Side note: This question was moved to SE.Programmers and then back to Stack Overflow. Discussion about this can be found in this meta question.

旁注:此问题已移至 SE.Programmers,然后又移回 Stack Overflow。关于这个的讨论可以在这个元问题中找到。

采纳答案by Kirill V. Lyadvinsky

I think that one should use the autokeyword whenever it's hard to say how to write the type at first sight, but the type of the right hand side of an expression is obvious. For example, using:

我认为auto当第一眼很难说出如何写类型时,应该使用关键字,但表达式右侧的类型是显而易见的。例如,使用:

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

to get the composite key type in boost::multi_index, even though you know that it is int. You can't just write intbecause it could be changed in the future. I would write autoin this case.

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

So if the autokeyword improves readability in a particular case then use it. You can write autowhen it is obvious to the reader what type autorepresents.

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

Here are some examples:

这里有些例子:

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)

回答by Jon Purdy

Use autoeverywhere you can—particularly const autoso that side effects are less of a concern. You won't have to worry about types except in the obvious cases, but they'll still be statically verified for you, and you can avoid some repetition. Where autoisn't feasible, you can use decltypeto express types semantically as contractsbased on expressions. Your code will look different, but it will be a positive change.

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

回答by spraff

Easy. Use it when you don't carewhat the type is. For example

简单。当您不在乎类型是什么时使用它。例如

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

All I care about here is that iis whatever's in the container.

我在这里关心的是i容器中的任何东西。

It's a bit like typedefs.

它有点像 typedef。

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

Here, I don't care whether hand ware floats or doubles, only that they are whatever type is suitable to express heights and weights.

在这里,我不在乎handw是 floats 还是 doubles,只关心它们是适合表达 heights 和 weights 的任何类型

Or consider

或者考虑

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

Here all I care about is that it's a suitable iterator, supporting operator++(), it's kind of like duck typing in this respect.

这里我关心的是它是一个合适的迭代器,支持operator++(),在这方面有点像鸭子打字。

Also the type of lambdas can't be spelled, so auto f = []...is good style. The alternative is casting to std::functionbut that comes with overhead.

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

I can't really conceive of an "abuse" of auto. The closest I can imagine is depriving yourself of an explicit conversion to some significant type -- but you wouldn't use autofor that, you'd construct an object of the desired type.

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

If you canremove some redundancy in your code without introducing side effects, then it mustbe good to do so.

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

Counterexamples (borrowed from someone else's answers):

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

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

Here we DO care what the type is, so we should write Someclass i;and for(unsigned x = y;...

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

回答by DarenW

Go for it. Use autoanywhere it makes writing code easier.

去吧。auto在任何地方使用它使编写代码更容易。

Every new feature in any language is going to get overused by at least some types of programmers. It is only through moderate overuse by some experienced programmers (not noobs) that the rest of the experienced programmers learn the boundaries of proper use. Extreme overuse is usually bad, but could be good because such overuse may lead to improvements in the feature or a better feature to replace it.

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

But if I were working on code with more than a few lines like

但是如果我处理的代码不止几行,比如

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 autosaves 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.

在类型被指示零次的情况下,我可能想要更改这些行以包含类型。第一个例子很好,因为类型被声明了一次,并且auto让我们不必两次编写凌乱的模板类型。C++++ 万岁。但是明确地显示类型零次,如果它在附近的行中不容易看到,让我感到紧张,至少在 C++ 及其直接后继者中。对于其他设计为在更高层次上具有更多抽象、多态性和通用性的语言,这很好。

回答by Gene Bushuyev

Yes, it can be overused to the detriment of readability. I suggest using it in the contexts where exact types are long, or unutterable, or not important for readability, and variables are short-lived. For example, iterator type usually is long and isn't important, so autowould work:

是的,它可能会被过度使用而损害可读性。我建议在确切类型很长,或无法表达,或对可读性不重要,并且变量寿命很短的上下文中使用它。例如,迭代器类型通常很长并且不重要,因此auto可以工作:

   for(auto i = container.begin(); i != container.end(); ++i);

autohere doesn't hurt readability.

auto这里不会损害可读性。

Another example is parser rule type, which can be long and convoluted. Compare:

另一个例子是解析器规则类型,它可能很长而且很复杂。相比:

   auto spaces = space & space & space;

with

r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&> spaces = 
   space & space & space;

On the other hand, when type is known and is simple, it's much better if it stated explicitly:

另一方面,当类型已知且简单时,如果明确说明会好得多:

int i = foo();

rather than

而不是

auto i = foo();

回答by Sean

At C++ and Beyond 2012in the Ask Us Anythingpanel, there was a fantastic exchange between Andrei Alexandrescu, Scott Meyers and Herb Sutter talking about when to use and not use auto. Skip to minute 25:03 for a 4 minute discussion. All three speakers give excellent points that should be kept in mind for when to notuse auto.

C++ and Beyond 2012Ask Us Anything小组中,Andrei Alexandrescu、Scott Meyers 和 Herb Sutter 就何时使用和不使用auto进行了精彩的交流。跳到 25:03 分钟进行 4 分钟的讨论。所有三个扬声器都给出了应牢记何时使用的优点auto

I highly encourage people to come to their own conclusion, but my take away was to use autoeverywhere unless:

我强烈鼓励人们得出自己的结论,但我的结论是在任何地方都使用auto除非

  1. It hurts readability
  2. There is concern about automatic type conversion (e.g. from constructors, assignment, template intermediate types, implicit conversion between integer widths)
  1. 它损害了可读性
  2. 担心自动类型转换(例如从构造函数、赋值、模板中间类型、整数宽度之间的隐式转换)

Liberal use of explicithelps reduce concern for the latter, which helps minimize the amount of time the former is an issue.

自由使用explicit有助于减少对后者的关注,这有助于最大限度地减少前者成为问题的时间。

Rephrasing what Herb said, "if you're not doing X, Y, and Z, use auto. Learn what X, Y, and Z are and go forth and use autoeverywhere else."

重新表述 Herb 所说的话,“如果您不做 X、Y 和 Z,请使用auto。了解 X、Y 和 Z 是什么,然后继续使用并auto在其他任何地方使用。”

回答by morotspaj

autocan be very dangerous in combination with expression templates which are used a lot by linear algebra libraries such as Eigen or OpenCV.

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.

Bugs caused by this type of mistakes are a major pain to debug. One possible remedy is to explicitly cast the result to the expected type if you are hellbent on using auto for the left-to-right declaration style.

由此类错误引起的错误是调试的主要痛苦。一种可能的补救措施是,如果您坚决使用 auto 作为从左到右的声明样式,则将结果显式转换为预期类型。

auto C = Matrix(A * B); // The expression is now evaluated immediately.

回答by rafak

I use autowihout restriction and didn't face any problem. I even sometimes end up using it for simple types like int. This makes c++ a higher level language for me, and allows to declare variable in c++ like in python. After writing python code, I even sometimes write e.g.

我使用auto没有限制并且没有遇到任何问题。我什至有时最终将它用于简单的类型,如int. 这使 c++ 成为我的高级语言,并允许像在 python 中一样在 c++ 中声明变量。写完python代码后,我什至有时会写eg

auto i = MyClass();

instead of

代替

MyClass i;

This is one case where I would say it is an abuse of the autokeyword.

在这种情况下,我会说这是对auto关键字的滥用。

Often I don't mind what is the exact type of the object, I'm more interested in its fonctionality, and as function names generally say something about the objects they return, autodoes not hurt: in e.g. auto s = mycollection.size(), I can guess that swill be a kind of integer, and in the rare case where I care about the exact type, let's check the function prototype then (I mean, I prefer to have to check when I need the info, rather than a priori when code is written, just in case it would be usefull someday, as in int_type s = mycollection.size()).

通常我不介意对象的确切类型是什么,我更感兴趣的是它的功能性,并且因为函数名称通常会说明它们返回的对象,auto不会受到伤害:例如auto s = mycollection.size(),我可以猜到这s将是一种整数,在我关心确切类型的罕见情况下,让我们检查函数原型(我的意思是,我更喜欢在需要信息时检查,而不是在编写代码时先验,只是以防有一天它会很有用,如int_type s = mycollection.size())。

Concerning this example from the accepted answer:

关于接受的答案中的这个例子:

for ( auto x = max_size; x > 0; --x )

In my code I still use autoin this case, and if I want xto be unsigned, then I use an utility function, named say make_unsigned, which expresses clearly my concerns:

在我的代码中,我仍然auto在这种情况下使用,如果我想x不签名,那么我使用一个名为 say 的实用程序函数make_unsigned,它清楚地表达了我的担忧:

for ( auto x = make_unsigned(max_size); x > 0; --x )

disclaimer: I just describe myuse, I'm not competent to give advices!

免责声明:我只是描述我的使用,我没有能力提供建议!

回答by Mantosh Kumar

One of the majorproblem with C++ program is it allows you to use the uninitialized variable. This leads us to nasty non deterministic program behavior. It should be noted that modern compiler now throw appropriate/message warning messages if program tires to use it.

C++ 程序的主要问题之一是它允许您使用未初始化的变量。这导致我们讨厌的非确定性程序行为。应该注意的是,如果程序厌倦使用,现代编译器现在会抛出适当的/消息警告消息。

Just to illustrate this, consider below c++ program:

为了说明这一点,请考虑以下 C++ 程序:

int main() {
    int x;
    int y = 0;
    y += x;
}

If I compile this program using modern compiler(GCC), it gives the warning. Such warning may not be very obvious if we are working with the real complex production code.

如果我使用现代编译器(GCC)编译这个程序,它会给出警告。如果我们正在处理真正复杂的生产代码,这种警告可能不是很明显。

main.cpp: In function 'int main()':

main.cpp:4:8: warning: 'x' is used uninitialized in this function [-Wuninitialized]

y += x;

    ^

main.cpp:在函数“int main()”中:

main.cpp:4:8:警告:在此函数中使用了未初始化的“x”[-Wuninitialized]

y += x;

    ^

================================================================================= Now if we change our program which uses auto, then compile we get the following:

================================================== ============================== 现在,如果我们更改使用auto的程序 ,然后编译,我们会得到以下结果:

int main() {
    auto x;
    auto y = 0;
    y += x;
}

main.cpp: In function 'int main()':

main.cpp:2:10: error: declaration of 'auto x' has no initializer

 auto x;

      ^

main.cpp:在函数“int main()”中:

main.cpp:2:10:错误:'auto x' 的声明没有初始化程序

 auto x;

      ^

With auto, it is not possible to use the uninitialized variable.This is major advantage which we may get(for free), if we start using auto.

对于 auto,不可能使用未初始化的变量。如果我们开始使用auto,这是我们可以获得(免费)的主要优势。

This concept and other great great modern C++ concept is explained by C++ expert Herb Shutterin his CppCon14talk:

C++ 专家Herb Shutter在他的CppCon14演讲中解释了这个概念和其他伟大的现代 C++ 概念:

Back to the Basics! Essentials of Modern C++ Style

回归基础!现代 C++ 风格的要点

回答by user2495422

One danger I have noted is in terms of references. e.g.

我注意到的一个危险是参考文献。例如

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

The problem is another_ref is not actually a reference in this case it is MyBigObject instead of MyBigObject&. You end up copying a big object without realising it.

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

If you are getting a reference directly from a method you might not think about what it actually is.

如果您直接从方法中获取引用,您可能不会考虑它实际上是什么。

auto another_ref = function_returning_ref_to_big_object();

you would need "auto&" or "const auto&"

你需要“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();