为什么我不能从lambda返回初始化列表 [英] Why I can not return initializer list from lambda

查看:142
本文介绍了为什么我不能从lambda返回初始化列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么这可能无效?

  auto foo=[](){
    return {1,2};     
  };

但是,这是有效的,因为初始化列表仅用于初始化向量,不返回自身:

However, this is valid since the initializer list is used just to initialize a vector not to return itself:

auto foo=[]()->std::vector<int>{
  return {1,2};     
};

为什么我不能返回 initializer list ?这可能是有用的。例如,可以用于初始化向量列表或具有某些默认值的lambda 。

Why I can not return initializer list? It could be useful. For example, a lambda that can be used to initialize a vector or a list or ... with some default values for something.

推荐答案

Lambda返回类型扣除使用 auto 这通常会推断 std :: initializer_list 很好。但是,语言设计者在返回语句([dcl.spec.auto] / 7)中禁止从支持的初始化器列表中扣除:

Lambda return type deduction uses the auto rules, which normally would have deduced std::initializer_list just fine. However, the language designers banned deduction from a braced initializer list in a return statement ([dcl.spec.auto]/7):


如果扣除是 return 语句,初始化程序是
braced-init-list ([dcl.init.list]

If the deduction is for a return statement and the initializer is a braced-init-list ([dcl.init.list]), the program is ill-formed.

原因是 std :: initializer_list 有引用语义( [dcl.init.list] / 6 ) 。
[]() - > std :: initializer_list< int> {return {1,2}; } 每一位都不如 []() - > const int& {return 1; } initializer_list 对象的返回数组的生命周期在lambda返回时结束,并且留下悬空指针(或两个)。

The reason for this is that std::initializer_list has reference semantics ([dcl.init.list]/6).
[]() -> std::initializer_list<int> { return {1, 2}; } is every bit as bad as
[]() -> const int & { return 1; }. The lifetime of the backing array of the initializer_list object ends when the lambda returns, and you are left with a dangling pointer (or two).

演示

#include <vector>

struct Noisy {
    Noisy()  { __builtin_printf("%s\n", __PRETTY_FUNCTION__); }
    Noisy(const Noisy&) { __builtin_printf("%s\n", __PRETTY_FUNCTION__); }
    ~Noisy() { __builtin_printf("%s\n", __PRETTY_FUNCTION__); }
};

int main()
{
    auto foo = []() -> std::initializer_list<Noisy> { return {Noisy{}, Noisy{}}; };
    std::vector<Noisy> bar{foo()};
}

输出:

Noisy::Noisy()
Noisy::Noisy()
Noisy::~Noisy()
Noisy::~Noisy()
Noisy::Noisy(const Noisy&)
Noisy::Noisy(const Noisy&)
Noisy::~Noisy()
Noisy::~Noisy()

请注意如何在所有 Noisy 对象后调用复制构造函数到目前为止已创建的文件已被删除。

Note how the copy constructors are called after all the Noisy objects created so far have been destroyed already.

这篇关于为什么我不能从lambda返回初始化列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆