#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 1
```
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 |