有什么理由不使用auto和C++基于范围的for循环?

use*_*973 4 c++

例如,循环:

std::vector<int> vec;
...
for (auto& c : vec) { ... }
Run Code Online (Sandbox Code Playgroud)

将迭代vec并通过引用复制每个元素.

有没有理由这样做?

for (int& c : vec) { ... }
Run Code Online (Sandbox Code Playgroud)

das*_*ght 5

这两个代码片段将生成相同的代码:auto编译器会发现底层类型是int,并且完全相同.

但是,选项auto更具"面向未来":如果稍后您决定int应该替换,比如uint8_t节省空间,则不需要查看代码,以查找对基础类型的引用可能需要更改,因为编译器会自动为您执行此操作.


Joh*_*ing 5

在任何可以使代码更好的地方使用 auto,但在其他地方没有。了解过度使用 auto 对可维护性的影响。

这里的问题真的是,是否有任何理由不应该将其auto用于任何可能的用途。

好吧,让我们首先解决一件事。的根本原因,为什么auto首先介绍了两折。

首先,它使复杂类型变量的声明更简单、更易于阅读和理解。在for循环中声明迭代器时尤其如此。考虑 C++03 伪代码:

for (std::vector <Foo>::const_iterator it = myFoos.begin(); it != myFoos.end(); ++it)
Run Code Online (Sandbox Code Playgroud)

随着myFoos的类型变得更加复杂,这会变得更加复杂。此外,如果myFoos以一种微妙的方式更改了类型,但以对刚刚编写的循环无关紧要的方式更改,则必须重新访问复杂的声明。这是一个在 C++11 中变得更简单的维护问题:

for (auto it = myFoos.begin(); it != myFoos.end(); ++it)
Run Code Online (Sandbox Code Playgroud)

第二,有其出现的一些情况无法处理,而不设施提供auto和它的兄弟姐妹,decltype。这出现在模板中。考虑(来源):

template<typename T, typename S>
void foo(T lhs, S rhs) {
  auto prod = lhs * rhs;
  //...
}
Run Code Online (Sandbox Code Playgroud)

在 C++03 中,prod如果lhs和的类型不同,则不能总是推断出 的类型rhs。在 C++11 中,这可以使用auto. 唉,也可以使用decltype,但这也与auto.


许多 C++ 精英建议您应该auto在任何可能的地方使用。Herb Sutter在最近的一次会议上指出了这样做的原因:

它更短。这样更方便。它更具前瞻性,因为如果您更改函数的返回类型,则auto可以正常工作。

然而,他们也承认“锋利的边缘”。有很多情况auto没有做你想要或期望的。当您想要进行类型转换时,这些锋利的边缘会割伤您。


因此,一方面我们有一个备受尊敬的阵营告诉我们“auto在任何可能的地方使用,但不能在其他地方使用”。然而,这对我来说并不合适。提供的大部分好处auto都是在我将称之为“首次写入时间”的时间提供的。你第一次写一段代码的时间。当您正在编写一大块全新的代码时,您可以继续使用auto几乎无处不在,并获得您期望的行为。在编写代码时,您确切地知道类型和变量发生了什么。我不了解你,但是当我编写代码时,我的脑海中会不断涌现想法。我想如何创建这个循环?我希望该函数返回什么样的东西,以便我可以在这里使用它?我怎样才能在 6 个月后快速、正确且易于理解地写这个?其中大部分内容从未直接在我编写的代码中表达出来,只是我编写的代码是这些想法的直接结果。

那时,使用auto会使编写此代码变得更简单更容易。我不必为有符号与无符号、引用与值、32 位与 64 位等的所有这小分钟感到负担。我只是编写auto,一切正常。

但这是我的问题auto。6 个月后,当我重新审视这段代码以添加一些主要的新功能时,我第一次编写代码时脑海中闪过的念头早已消失。我的缓冲区很久以前就被刷新了,这些想法都不再与我同在了。如果我的工作做得很好,那么这些想法的精髓就直接在我写的代码中表达出来了。只需查看我的函数和数据类型的结构,我就可以对我的想法进行逆向工程。

如果auto洒在各处,大部分的认知都会丢失。我不知道我在想这个数据类型会发生什么,因为现在它是推断出来的。如果与运算符之间存在微妙的关系,则该关系不再由数据类型表示——它只是auto.

维护变得更加困难,因为不,我必须重新创建大部分想法。微妙的关系变得更加模糊,一切都变得更加难以理解。

所以我不喜欢auto在任何可能的地方使用。我认为这使得维护比它必须的更难。这并不是说我认为auto应该只在需要的地方使用它。相反,这是一种平衡行为。我用来判断我的(或任何人的)代码质量的四个标准是:效率、正确性、健壮性和可维护性。没有特别的顺序。如果我们设计一个auto使用范围,其中一侧是“纯可选”而另一侧是“严格要求”,我觉得一般来说,我们越接近“纯可选”,可维护性受到的影响就越大。

所有这一切,最后,我的哲学可以概括为:

auto在可以使代码更好的地方使用,但不能在其他地方使用。了解auto过度自由使用对可维护性的影响。