新关键字“auto”;什么时候应该使用它来声明变量类型?
可能的重复:
C++0x auto 关键字多少就太多了
我们(作为一个社区)是否有足够的经验来确定汽车何时和/或是否被滥用?
我真正想要的是关于
- 何时使用 auto
- 何时应避免的
最佳实践指南简单的经验法则可以在 80% 的情况下快速遵循。
作为上下文,这个问题是由我的回答引发的
Possible Duplicate:
How much is too much with C++0x auto keyword
Have we (as a community) had enough experience to determine when and/or whether auto is being abused?
What I am really looking for is a best practices guide on
- when to use auto
- when it should be avoided
Simple rules of thumb that can quickly be followed in 80% of cases.
As a context this question is sparked by my response here
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我认为当该类型在项目中工作(或将要工作)的共同程序员中非常知名时,可以使用
auto
,例如在以下代码中:或者,更一般地说,
但是当类型不是很知名并且不经常使用时,那么我认为
auto
似乎会降低可读性,例如这里:而在前一种情况下,使用
auto
code> 看起来很好并且不会降低可读性,因此,可以广泛使用,但在后一种情况下,它会降低可读性,因此不应使用。另一个可以使用
auto
的地方是当您使用new
1 或make_*
函数时,例如这里:在这里它非常好,因为它减少了键盘的使用,而不降低可读性,因为任何人都可以通过查看代码来知道正在创建的对象的类型。
<子>1。不过,请避免使用 new 和原始指针。
有时,类型是如此无关紧要,甚至不需要类型的知识,例如在表达式模板中;事实上,实际上不可能(正确地)编写类型,在这种情况下,
auto
对程序员来说是一种解脱。我编写了表达式模板库,可用作:输出:
现在将上面的代码与以下不使用
auto
的等效代码进行比较:如您所见,在这种情况下,
auto
会让您的生活变得更加轻松。上面使用的表达方式非常简单;想想一些更复杂的表达式的类型:这样的表达式的类型会更加庞大和丑陋,但是感谢
auto
,我们现在可以让编译器推断表达式的类型。因此,底线是:关键字
auto
可能会提高或降低代码的清晰度和可读性,取决于上下文。如果上下文清楚地表明它是什么类型,或者至少应该如何使用它(在标准容器迭代器的情况下),或者甚至不需要实际类型的知识(例如在表达式中) templates),那么应该使用auto
,如果上下文没有说清楚并且不是很常见(比如上面的第二种情况),那么它最好避免。
I think when the type is very well-known amongst the co-programmers who work (or would work) in your project, then
auto
can be used, such as in the following code:Or, more generally,
But when the type is not very well-known and infrequently used , then I think
auto
seems to reduce readability, such as here:While in the former case, the usage of
auto
seems very good and doesn't reduce readability, and therefore, can be used extensively, but in the latter case, it reduces readabilty and hence shouldn't be used.Another place where
auto
can be used is when you usenew
1 ormake_*
functions , such as here:Here it is very good, as it reduces the use of keyboard, without reducing the readability, as anyone can know the type of objects being created, just by looking at the code.
1. Avoid using
new
and raw-pointers though.Sometime, the type is so irrelevant that the knowledge of the type is not even needed, such as in expression template; in fact, practically it is impossible to write the type (correctly), in such cases
auto
is a relief for programmers. I've written expression template library which can be used as:Output:
Now compare the above code with the following equivalent code which doesn't use
auto
:As you can see, in such cases
auto
makes your life exponentially easier. The expressions used above are very simple; think about the type of some more complex expressions:The type of such expressions would be even more huge and ugly, but thanks to
auto
, we now can let the compiler infer the type of the expressions.So the bottomline is: the keyword
auto
might increase or decrease clarity and readability of your code, depending on the context. If the context makes it clear what type it is, or at least how it should be used (in case of standard container iterator) or the knowledge of the actual type is not even needed (such as in expression templates), thenauto
should be used, and if the context doesn't make it clear and isn't very common (such as the second case above), then it should better be avoided.简单的。当您不关心类型是什么时使用它。例如,
我在这里关心的是
i
是容器中的任何内容。这有点像 typedef。
在这里,我不关心
h
和w
是浮点数还是双精度数,只关心它们是适合表达身高和体重的类型 。或者考虑
这里我所关心的是它是一个合适的迭代器,支持
operator++()
,在这方面它有点像鸭子类型。而且 lambda 的类型无法拼写,因此
auto f = []...
是很好的风格。另一种方法是转换为 std::function ,但这会带来开销。我真的无法想象对
auto
的“滥用”。我能想到的最接近的方法是剥夺自己对某种重要类型的显式转换——但您不会为此使用 auto ,而是构造一个所需类型的对象。如果您可以删除代码中的一些冗余而不引入副作用,那么这样做一定是件好事。
Easy. Use it when you don't care what the type is. For example
All I care about here is that
i
is whatever's in the container.It's a bit like typedefs.
Here, I don't care whether
h
andw
are floats or doubles, only that they are whatever type is suitable to express heights and weights.Or consider
Here all I care about is that it's a suitable iterator, supporting
operator++()
, it's kind of like duck typing in this respect.Also the type of lambdas can't be spelled, so
auto f = []...
is good style. The alternative is casting tostd::function
but that comes with overhead.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 useauto
for that, you'd construct an object of the desired type.If you can remove some redundancy in your code without introducing side effects, then it must be good to do so.
我会应用与 C# 中的
var
相同的规则:自由地使用它。它增加可读性。除非变量的类型实际上很重要,需要明确说明,在这种情况下应该这样做(废话)。尽管如此,我仍然认为(特别是在静态类型语言中)编译器在为我们跟踪类型方面比我们更好。大多数时候,精确类型无论如何都不是非常重要(否则接口在实践中将无法工作)。更重要的是要了解哪些操作是允许的。上下文应该告诉我们这一点。
此外,
auto
实际上可以通过防止初始化中不需要的隐式转换来防止错误。通常,如果y
不是Foo
类型并且存在隐式转换,则语句Foo x = y;
将执行隐式转换。这就是首先要避免隐式转换的原因。不幸的是,C++ 已经有太多这样的东西了。编写
auto x = y;
原则上可以避免这个问题。另一方面,应该清楚的是,当我执行假设整数中的这个或那个字节数的计算时,必须知道并且应该清楚地说明变量的显式类型。
并非所有情况都如此明确,但我认为大多数情况都是如此,并且
Eric Lippert,C# 编译器团队的主要开发人员, 的说法与关于
var
。I’d apply the same rule as for
var
in C#: use it liberally. It increases readability. Unless the type of a variable is actually important enough to be stated explicitly, in which cases this should be done (duh).Still, I maintain that (especially in statically typed languages) the compiler is much better at tracking types for us than we are. Most of the time, the exact type isn’t terribly important anyway (otherwise interfaces wouldn’t work in practice). It’s more important to be aware of which operations are permitted. Context should tell us that.
Furthermore,
auto
can actually prevent bugs, by preventing unwanted implicit conversions in initialisations. Generally, the statementFoo x = y;
will perform an implicit conversion ify
isn’t of typeFoo
and an implicit conversion exists. This is the reason to avoid having implicit conversions in the first place. Unfortunately, C++ has much too many of them already.Writing
auto x = y;
will prevent this problem in principle.On the other hand, it should be clear that when I’m performing calculations that assume this or that number of bytes in an integer, the explicit type of the variable must be known and should be clearly stated.
Not all cases are as clear cut but I maintain that most are, and that
Eric Lippert, principal developer on the C# compiler team, has stated much the same with regards to
var
.我认为你的第一个问题的答案是否定的。我们知道足够的知识来整理一些关于何时使用或避免
auto
的指南,但它们仍然留下相当多的情况,我们目前能说的最好的办法是我们还不能提供太多帮助关于他们的客观建议。您几乎必须使用它的明显情况是在模板中,当您想要(例如)正确的类型来保存对两个泛型参数进行某些操作的结果时。在这种情况下,滥用的唯一可能性实际上并不是滥用
auto
本身,而是您正在执行的一般操作类型(或您正在编写的模板类型等) .) 是你最好避免的事情。至少在某些情况下,您显然需要避免
auto
。如果您使用类似代理类型的东西,其中您依赖于 proxy->target 的转换来完成手头的部分工作,auto
将(尝试)创建一个目标与源的类型相同,因此不会发生转换。在某些情况下,这可能只是延迟转换,但在其他情况下,它根本不起作用(例如,如果代理类型不支持分配,这通常是这种情况)。另一个例子是,当您需要确保特定变量具有特定类型(例如外部接口)时。例如,考虑将网络掩码应用于 IP (v4) 地址。为了便于讨论,我们假设您正在使用地址的各个八位字节(例如,将每个八位字节表示为
unsigned char
),因此我们最终得到类似octets[0 ] &掩码[0]
。由于 C 的类型提升规则,即使两个操作数都是unsigned char
,结果通常也是int
。我们需要结果是一个unsigned char
(即一个八位字节),而不是一个int
(通常是4个八位字节)。因此,在这种情况下,auto
几乎肯定是不合适的。尽管如此,在很多情况下仍然需要做出判断。对于这些情况,我自己的倾向是将
auto
视为默认值,并且仅在至少有点像我引用的后一种情况的情况下使用显式类型上面 - 即使正确操作不需要特定类型,但我确实想要特定类型,即使这可能涉及隐式转换。我的猜测(但这只是猜测)是,随着时间的推移,我可能会更加倾向于这个方向。随着我越来越习惯编译器挑选类型,我会发现在相当多的情况下,我目前认为应该指定类型,但我确实不需要,并且代码会没事吧。
我怀疑我们中的很多人(年龄越大/经验越丰富,可能会变得越糟糕)会使用显式类型,其原因最终可以追溯到对性能的一些感觉,并相信我们的选择会提高性能。有时我们可能甚至是对的——但正如我们大多数拥有丰富经验的人所发现的那样,我们的猜测常常是错误的(特别是当它们基于隐式假设时),并且编译器和随着时间的推移,处理器通常也会在这些事情上变得更好。
I think the answer to your first question is sort of no. We know enough to put together some guidelines about when to use or avoid
auto
, but they still leave quite a few cases where the best we can currently say is that we can't yet give much in the way of objective advice about them.The obvious case where you nearly have to use it is in a template when you want (for example) the proper type to hold the result of some operation on two generic parameters. In a case like this, the only possibility of abuse wouldn't really be abuse of
auto
itself, but whether the general type of operation you're doing (or type of template you're writing, etc.) is something you'd be better off avoiding.There are also at least a few situations where you clearly need to avoid
auto
. If you're using something like a proxy type where you're depending on the conversion from proxy->target to do part of the job at hand,auto
will (attempt to) create a target of the same type as the source so that conversion won't happen. In some cases, that may just delay the conversion, but in others it won't work at all (e.g., if the proxy type doesn't support assignment, which is often the case).Another example would be when you need to assure that a particular variable has a specific type for the sake of something like an external interface. Just for example, consider applying the network mask to an IP (v4) address. For the sake of argument, let's assume you're working with the individual octets of the address (e.g., representing each as an
unsigned char
), so we end up with something likeoctets[0] & mask[0]
. Thanks to C's type promotion rules, even if both operands areunsigned char
s, the result is typically going to beint
. We need the result to be anunsigned char
though (i.e., one octet) not anint
(typically 4 octets) though. As such, in this situation,auto
would almost certainly be inappropriate.That still leaves a lot of cases where it's a judgement call though. My own tendency for these cases is to treat
auto
as the default, and only use an explicit type in cases that are at least a little like the latter case I've cited above -- even if a particular type isn't needed for correct operation that I really want a particular type, even if that might involve an implicit conversion.My guess (but it is just a guess) is that over time, I'll probably tend even more in that direction. As I get more accustomed to the compiler picking out types, I'll find that a fair number of cases where I currently think I should specify the type, I really don't need to and the code will be just fine.
I suspect a lot of us (and the older/more experienced we are, probably the worse we'll be about it) will use explicit types for reasons that ultimately trace back to some feeling about performance, and believing that our choice will improve performance. Part of the time we may even be right -- but as most of us with that much experience have found, our guesses are often wrong (especially when they're based on implicit assumptions), and compilers and processors generally get better at such things over time as well.
我使用过具有完整类型推断的语言。我认为没有理由不在技术上可行的地方放置
auto
*。事实上,我可能已经编写了auto i = 0;
,其中int
比auto
短了一个字符。我什至不确定我是否这样做,因为最根本的是:我不关心清单类型。*:例如
auto int[] = { 0, 1, 2, 3 }
不起作用。I've used languages with full type inference. I see no reason not to put
auto
everywhere it's technically possible*. In fact I may have already writtenauto i = 0;
, whereint
is one character shorter thanauto
. I'm not even sure that I did because the bottom is: I don't care for manifest typing.*: for instance
auto int[] = { 0, 1, 2, 3 }
doesn't work.仅将其与长重复类型一起使用,例如长模板和 lambda 函数类型。如果可以的话尽量避免它,让事情变得清楚。
Only use it with long repetitive types such as long templates and lambda function types. Try to avoid it if you can to make things clear.