
#include<iostream> #include<vector> using namespace std; struct test { vector<int> vec; test() : vec(1) {} int new_node(int i) { int n = vec.size(); vec.push_back(i); return n; } void func(int i) { vec[0] = new_node(i); cout << vec[0] << endl; } }; int main() { test t; for(int i = 0; i < 5; i++) t.func(i); return 0; } (原代码比较复杂,这里经过化简,就是vec[0]存当前的长度,每次func就vec后面加一个数)
学的工地 C++,感觉好像没什么特别的实现,但就是产生奇怪的问题
本地用比较旧的 G++会产生运行时错误
而找了其它的在线 IDE 下,C++11 会输出
0 0 3 3 5 而在 C++17 下是我所期望的
1 2 3 4 5 想问问 V 友们这个具体出现的问题是哪里,要怎样才能规避这种现象
1 May725 2020-01-06 21:34:44 +08:00 via iPhone 你这贴出来的代码没问题 |
3 lcdtyph 2020-01-06 21:50:54 +08:00 ``` vec[0] = new_node(i); ``` 这行,new_node(i)里面有对 vec 的 expand 操作,这在 c++17 之前有可能会导致 vec[0]这个左值失效。 c++17 规定了求值顺序 |
4 wevsty 2020-01-06 21:57:08 +08:00 试了一下 icc 16.0.3 结果是 12345 clang 9.0 结果是 12345 MSVC 19.23 结果是 12345 只有 gcc 给的结果是 00335 我觉得应该是你这个代码触发了 gcc 的什么奇怪的优化或者 bug,不是一个 ub。 |
5 lcdtyph 2020-01-06 22:00:45 +08:00 via iPhone |
6 wevsty 2020-01-06 22:26:00 +08:00 @lcdtyph 仔细看了一下标准,确实 C++17 标准新增了一条。 每个简单赋值表达式 E1=E2 和每个复合赋值表达式 E1@=E2 中,E2 的每个值计算和副作用均按顺序早于 E1 的每个值计算和副作用。 这个是明确了需要先算 E2,之前的标准并没有这样的要求,没有要求那就是 UB 了。 |
7 Caturra OP |