7

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

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

#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,还是语言改变了?

PS我知道如何使用static const auto& results作品来解决这个问题,就像前面提到的那样,这只是一个关于语言极端情况的问题。

4

1 回答 1

7

这与保证复制省略有关,这是 C++17 中的一个新语言特性。

这一行(减少):

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

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

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

在 C++17 中,它的行为完全类似于:

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

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

于 2019-12-17T18:50:31.447 回答