【问题标题】:Same clang, different results for std::initializer_list program with -std=c++14/-std=c++17使用 -std=c++14/-std=c++17 的 std::initializer_list 程序的相同clang,不同的结果
【发布时间】:2019-12-17 18:36:22
【问题描述】:

首先这是一个好奇的问题,在现实生活中我永远不会写这样的代码。

以下代码的行为与 -O3 -std=c++14 和 -O3 -std=c++17 标志不同,在 C++14 中我得到了错误的分配,我假设从垃圾 std:: 复制构造字符串:

#include<algorithm>
#include<numeric>
#include<vector>
#include<string>
#include<iostream>

using namespace std;
static auto results = std::initializer_list<string>{"1                               ",
"2"};
string f() {

    auto result = std::accumulate(results.begin(), results.end(), string(""));
    return result;

}

int main()
{
    return f().size();
}

https://godbolt.org/z/H-Xzei

我的猜测是 C++17 版本使底层数组的存活时间比 C++14 版本长,但我发现在 cppreference 上从 C++14 到 C++17 的初始化列表没有相关变化,所以我很困惑. 这只是UB是UB,还是语言改变了?

附:我知道如何解决这个问题,使用static const auto&amp; results 作品,就像之前提到的,这只是一个关于语言极端情况的问题。

【问题讨论】:

  • AFAIK 生命周期的变化是从 C++11 到 C++14。代码在 C++14 或 C++17 中应该没问题,所以不确定发生了什么。 GCC 在 14 或 17 模式下工作。
  • 也适用于 MSVC 上的 14 和 17。

标签: c++ clang language-lawyer c++17 stdinitializerlist


【解决方案1】:

这与保证复制省略有关,这是 C++17 中的一种新语言功能。

这一行(减少):

static auto results = std::initializer_list<string>{x, y};

在 C++14 中构造一个初始化列表,然后将其移动到 results - 它立即悬空,因为 initializer_list 不管理任何生命周期(std::initializer_list 有一个支持 const 数组,其生命周期与初始对象 - 一旦初始 initializer_list 在行尾被销毁,后备数组也是如此。

换句话说,在 C++14 中,该程序具有未定义的行为。

在 C++17 中,它的行为与:

static std::initalizer_list<string> results{x, y};

在这种情况下,后备数组与results 具有相同的生命周期,即程序的长度。该程序具有明确定义的行为。

【讨论】:

  • 所以只有 clang 是正确的? Cppreference 可能需要更新,因为它声明:一个临时的
  • @NathanOliver-ReinstateMonica 只有 clang 关于什么是正确的? cppreference 需要更新吗?
  • 没关系,我现在明白了。 std::initializer_list&lt;int&gt; i3 = { 1, 2, 3 }; 很好,但 std::initializer_list&lt;int&gt; i3 = std::initializer_list&lt;int&gt;{ 1, 2, 3 }; 让它悬空,因为“数组”被右侧的 std::initializer_list 临时吸收了。
  • @NathanOliver-ReinstateMonica 是的。仅在 17 中发生变化,在第 2 种情况下没有临时变化。
  • 哇,这太疯了,但有道理,只是我自己在一千年内都无法弄清楚,尽管我知道有保证的 cpy 省略。
猜你喜欢
  • 1970-01-01
  • 2012-07-09
  • 2019-06-06
  • 2021-12-02
  • 2017-08-15
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多