为什么"auto"在推导返回值时不能接受大括号的初始化列表?



[现代有效C++] 说:

template<class T>
void f(T t){}
int main(){
    f({1,2,3});
}

编译会失败,因为当模板实例化时,必须知道 T 的类型,而这里的 {1,2,3} 是大括号的 init-list。应该像这样修复:

auto x={1,2,3};//auto deduces x to std::initializer_list
f(x);

我可以理解这一点,但是我的问题:

为什么书中一直说,当用"auto"进行返值扣除时,它不能接受和推导大括号的初始化列表?

auto f()
{
    return {1,2,3};
}

编译失败。

Emmmmm,如果这是 C++14 标准的一部分,我不明白为什么会有这样的限制?它继续说:

auto resetV=[&v](const auto& newValue){v=new Value;}

"newValue"前面的"auto"也不能接受{1,2,3}。为什么我们有这样的 2 个限制?

我想也许从语言设计的角度来看,在进行类型推断时会有一些困惑?只是一个猜测。这些设计决策有什么线索吗?这让我困惑了好几天。

谢谢。

std::initializer_list是对

匿名数组的引用。

数组本身位于创建initializer_list的块范围内。

std::initializer_list<int> f() {
  return {1,2,3};
}

几乎完全没用,因为数组的生存期是f体,而引用它的initializer_list存在于几乎完全不相交的代码时期。

使用该initializer_list几乎可以肯定是未定义的行为。 你可能会问它的大小,它是否为空,这可能是定义的行为(不知道,不关心检查),但你绝对不能检查它的内容。

初始值设定项列表是对数据的引用,而不是数据的副本。

如果:

auto f() {
  return {1,2,3};
}

推论自己是上述,它几乎永远不会有用。

例外,auto x = {1,2,3};有效,是唯一可以从一组{}推断出initailizer_list<int>的情况。 (在C++11中,auto x{1};也是如此,但这被贬低了)。

为什么书中一直说,当用"auto"进行返值扣除时,它不能接受和推导大括号的初始化列表?

并不是说它"无法推断"。只是不允许。仔细考虑以下代码:

#include <initializer_list>
auto f() -> std::initializer_list<int>
{
    return {1,2,3};
}

它编译吗?是的。安全吗?不。这可能会在底层阵列的生存期内引入各种问题。 std::initializer_list不应像容器一样使用。

最新更新