相同的 clang,std::initializer_list 程序与 -std=c++14/-std=c++17 的不同结果
Same clang, different results for std::initializer_list program with -std=c++14/-std=c++17
首先这是一个好奇的问题,我在现实生活中永远不会写这样的代码。
以下代码的行为与 -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();
}
我的猜测是 C++17 版本使底层数组存活的时间比 C++14 版本长,但我发现在 cppreference 上从 C++14 到 C++17 的初始化列表没有相关变化,所以我我很困惑。
这只是 UB 是 UB,还是语言发生了变化?
P.S。我知道如何解决这个问题,使用 static const auto& results
可以解决这个问题,就像之前提到的那样,这只是关于语言极端情况的问题。
这与保证复制省略有关,这是 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
相同,即程序的长度。该程序具有明确定义的行为。
首先这是一个好奇的问题,我在现实生活中永远不会写这样的代码。
以下代码的行为与 -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();
}
我的猜测是 C++17 版本使底层数组存活的时间比 C++14 版本长,但我发现在 cppreference 上从 C++14 到 C++17 的初始化列表没有相关变化,所以我我很困惑。 这只是 UB 是 UB,还是语言发生了变化?
P.S。我知道如何解决这个问题,使用 static const auto& results
可以解决这个问题,就像之前提到的那样,这只是关于语言极端情况的问题。
这与保证复制省略有关,这是 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
相同,即程序的长度。该程序具有明确定义的行为。