为什么直接列表初始化与auto被认为是坏的或不是首选的?

And*_* DM 9 c++ initialization auto c++11 type-deduction

我养成了使用直接列表初始化编写代码的习惯,因为它更有效,并且防止隐式缩小非常有用:

int i {0};
string s {""};
char c {'a'};
bool b {false};

auto num {100}; // But this??
Run Code Online (Sandbox Code Playgroud)

但是当谈到自动说明符时,我听说它被认为是坏的或者不喜欢这样写它,为什么呢?

Tar*_*ama 11

以下是使用该语法失败的示例:

struct Foo{};

void eatFoo (const Foo& f){}

int main() {
    Foo a;
    auto b{a};
    eatFoo(b);
}
Run Code Online (Sandbox Code Playgroud)

你可能会认为这很好:b应该是一个Foo并传递给eatFoo.不幸的是,这会导致以下编译器错误:

prog.cpp:11:10: error: invalid initialization of reference of type 'const Foo&' from expression of type 'std::initializer_list<Foo>'
  eatFoo(b);
Run Code Online (Sandbox Code Playgroud)

如你所见,b实际上是类型std::initializer_list<Foo>.在这种情况下,当然不是我们想要的.如果我们改变它auto b = a,这很好.然后,如果我们仍然想要使用auto,但明确说明类型,我们可以将其更改为auto b = Foo{a}并让编译器忽略副本.

  • "那么如果我们仍然想要使用`auto`,但明确说明类型," - 这真的没有意义.`auto`的重点是避免说明类型.我知道在C#中确实有人编写`var x =(string)null;`而不是`string x = null;`,但它们只是一小部分而且我从来没有见过任何人真正捍卫编写这样的代码.我无法想象在C++中它的有效论据. (4认同)
  • 它是[几乎总是自动风格]的一部分(http://herbsutter.com/2013/08/12/gotw-94-solution-aaa-style-almost-always-auto/).由于它有一些非常有影响力的人的讨论,包括它似乎是恰当的. (2认同)
  • @TartanLlama感谢您的链接.在评论之外没有提到的一件事,并且在我看来,一个非常强烈的理由*反对*那种风格,是它支持显式转换运算符.这些转换运算符通常是明确的,有充分理由,默认情况下不应该使用它们,只有在用户明确请求时才使用它们.例如,给定`struct S {explicit S(int); `s,`s s = 3;`编译失败.`auto s = S {3};`被接受.系统地使用`auto v = T {i};`语法意味着编译器获得警告可能出错的机会较少. (2认同)