直接列表初始化的自动规则

时间:2017-08-09 00:18:26

标签: c++ c++17

我只是想学习新的c ++ 17更改“直接列表初始化的自动规则”

很少有stackoverflow问题线程有答案,比如它不安全 Why is direct-list-initialization with auto considered bad or not preferred?

尝试了一个选定的答案以理解

#include <typeinfo>
#include <iostream>

struct Foo{};

void eatFoo (const Foo& f){}

int main() {
    Foo a;
    auto b{a};
    eatFoo(b);
    std::cout << "a " << typeid(a).name() << '\n';
    std::cout << "b " << typeid(b).name() << '\n';

}

但令我惊讶的是它编译时没有任何警告或编译错误 输出

a 3Foo
b 3Foo
Program ended with exit code: 0

这是否意味着现在使用auto进行直接初始化是安全的

例如像这样

auto x { 1 };

1 个答案:

答案 0 :(得分:6)

&#34;安全&#34;是在旁观者的眼中。

C ++ 14的行为是安全的&#34;,因为它定义了结果。 auto var_name{expr}会创建一个元素的initializer_list

C ++ 17使得auto var_name{expr}导致与auto var_name = expr;相同的类型推导。只要您预计会出现这种情况,那么它就是安全的&#34;。但它已经不再安全了#34;比旧的行为。

然后,这是一种向后与C ++ 14行为不兼容的语言变化。按照这个标准,它并不安全&#34;,因为C ++ 14用户期望你的代码做的事情与C ++ 17编译器不同。所以它会产生一些微妙的混乱,这可能不安全。

然后出现了#34;统一初始化&#34;应该是&#34;制服&#34; (即:在所有地方的相同规则下执行相同类型的初始化),但auto var_name{expr}将执行与auto var_name = {expr}非常不同的操作。后者仍然是initializer_list;前者将是复制/移动。通过这个标记,它不安全&#34;假设&#34;统一初始化&#34;是统一的。

然后,C ++ 17的行为有时候是你真正想要的。将变量从单个值初始化为您,意味着复制/移动它。毕竟,如果你已经完成decltype(expr) var_name{expr},那就是你得到的行为。所以从这个角度来看,它似乎是安全的#34;行为。

至少,我们可以说通过两条规则可以更好地教育这种情况:

  1. auto变量的直接列表初始化意味着&#34;将表达式复制/移动到变量中,如果您提供多个表达式,则表示您使用了错误的语法。&# 34;
  2. auto变量的复制列表初始化意味着&#34;制作initializer_list,如果您提供无法执行此操作的值,则表明您使用了错误语法&#34;
  3. 也许简单性会产生一种“安全感”。

    启动这些更改的

    The document通过坚持上述规则返回堆叠绑定initializer_list,从而减​​少了意外UB的可能性。这是&#34; safe&#34;。

    的一个定义

    所以这一切都取决于你的意思&#34;安全&#34;。