首页  >  文章  >  后端开发  >  为什么 GCC 和 Clang 之间 `std::initializer_list` 返回值的生命周期不同?

为什么 GCC 和 Clang 之间 `std::initializer_list` 返回值的生命周期不同?

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-10-28 10:06:021050浏览

Why Does the Lifetime of an `std::initializer_list` Return Value Differ Between GCC and Clang?

std::initializer_list 的生命周期返回值:GCC 与 Clang 行为

在提供的代码中,您将返回一个 std ::initializer_list 来自函数并观察意外的析构函数行为。具体来说,从函数返回的数组在您可以访问其元素之前就被销毁了。

根本问题源于这样一个事实:根据 C 标准,std::initializer_list 具有一个元素数组,该数组是构造的生命周期与initializer_list相同。这意味着,默认情况下,数组会在函数中的 return 语句末尾被销毁。

GCC 的实现遵循此行为,而 Clang 则不然。 Clang 在返回语句结束后维持数组的生命周期,这不符合标准。然而,Clang 的行为显得不一致,因为对象析构函数从未被调用。

复制列表初始化和编译器解释

带有花括号的 init- 的 return 语句list 通过 copy-list-initialization 初始化返回值,这意味着它复制初始化现有对象。在这种情况下,临时的initializer_list对象是从大括号括起来的列表中复制初始化的。随后,另一个initializer_list对象从第一个对象开始复制初始化。

标准规定数组的生命周期与initializer_list对象相同,但由于创建了initializer_list的多个副本,因此不清楚哪个对象的生命周期决定数组的生命周期。

GCC 通过考虑返回的initializer_list 对象的生命周期来解释标准,导致数组过早销毁。然而,8.5.4/6 中提供的示例表明数组的生命周期应延伸到封闭表达式的末尾,包括接收函数。

编译器行为和标准歧义总结

  • GCC:遵循标准并在 return 语句末尾销毁数组。
  • Clang:将数组的生命周期延长到 return 语句之外,但无法正确销毁对象析构函数。
  • 关于哪个initializer_list对象决定数组的生命周期的标准不明确。

建议

为了避免意外行为,通常不建议这样做按值返回 std::initializer_list。如果您需要传递可变数量的对象,请考虑使用容器类,例如 std::vector。

以上是为什么 GCC 和 Clang 之间 `std::initializer_list` 返回值的生命周期不同?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn