跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 实在不懂,求问这段代码是不是踩了未定义行为的坑
未分類
4 5 月 2020

实在不懂,求问这段代码是不是踩了未定义行为的坑

实在不懂,求问这段代码是不是踩了未定义行为的坑

資深大佬 : Caturra 75

#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 友们这个具体出现的问题是哪里,要怎样才能规避这种现象

大佬有話說 (7)

  • 資深大佬 : May725

    你这贴出来的代码没问题

  • 主 資深大佬 : Caturra

    @May725 我也觉得没问题,但不同编译器的表现说明我代码里有坑

  • 資深大佬 : lcdtyph

    “`
    vec[0] = new_node(i);
    “`
    这行,new_node(i)里面有对 vec 的 expand 操作,这在 c++17 之前有可能会导致 vec[0]这个左值失效。
    c++17 规定了求值顺序

  • 資深大佬 : wevsty

    试了一下
    icc 16.0.3 结果是 12345
    clang 9.0 结果是 12345
    MSVC 19.23 结果是 12345
    只有 gcc 给的结果是 00335
    我觉得应该是你这个代码触发了 gcc 的什么奇怪的优化或者 bug,不是一个 ub。

  • 資深大佬 : lcdtyph

    @wevsty
    这就是 ub,不要随便怀疑编译器…
    你可以把 vec 初始化时候的那个参数 1 改成 10,这样保证 5 次 push 都不会让内部的地址失效。

  • 資深大佬 : wevsty

    @lcdtyph
    仔细看了一下标准,确实 C++17 标准新增了一条。
    每个简单赋值表达式 E1=E2 和每个复合赋值表达式 [email protected]=E2 中,E2 的每个值计算和副作用均按顺序早于 E1 的每个值计算和副作用。
    这个是明确了需要先算 E2,之前的标准并没有这样的要求,没有要求那就是 UB 了。

  • 主 資深大佬 : Caturra

    @lcdtyph 感谢,旧编译器主动扩容后虽然也有奇怪的行为,不过起码知道哪里出问题了

    @wevsty 没想到这在 C++17 才有明确的规定,算是学习了

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具