【问题标题】:Trying to avoid if-else statement inside for-loop but the code seems to have some errors试图避免在 for 循环中使用 if-else 语句,但代码似乎有一些错误
【发布时间】:2020-04-10 16:31:17
【问题描述】:

这个 sn-p 工作得很好。

for (int i = 0; i < 1; i++) // for some other purpose
{
  // some other code

  double** angle = new double* [10];   // for a 2D matrix
  for (int j = 0; j < 10; j++)
  {
     angle[j] = new double [3];

     if (j == 0) 
            angle[j][0] = 2;          // focused on the first column for now
     else 
            angle[j][0] = angle[j-1][0]+3;

     std::cout << angle[j][0] << std::endl;
  }

  for (int i = 0; i < 10; i++)
     delete[] angle[i];
     delete[] angle; 
}

我试图不在循环内使用条件语句。如果我用以下行替换它,代码将停止工作。请帮助我理解它。

angle[j][0] = (j == 0) * 2 + (j != 0) * (angle[j-1][0] + 3);

Ubuntu 16.04 LTS 上使用 g++ -std=c++11 -o out main.cpp; ./out

【问题讨论】:

  • 为了什么目的你想使用条件语句作废?可读性?表现?使用 delete[] 格式化循环也具有误导性。
  • @KonstantinStupnik:感谢您指出这一点。我正在听一位教授的讲座,他有点建议。拥有非 IT 背景,我没有太多时间来验证或交叉检查他的陈述。如果您修复解除分配,我将不胜感激。请分享您的意见。
  • 虽然编译器可能会进行优化,但并不严格要求 - 数学运算本质上不是短路的。因此,当j 为零时,没有什么可以阻止编译器在修改后的代码中评估angle[j-1][0] + 3(实际上,可以在评估表达式j==0j != 0 之前评估它)——这会产生未定义的行为.
  • 至少 unindent 'delete[] angle;'行,我建议在循环体周围加上大括号,也可以删除。这几乎是一个宗教问题,是否在单个语句主体周围放置大括号,但从长远来看,IMO 最好始终使用它们。

标签: c++ for-loop conditional-operator


【解决方案1】:

您正在尝试使用 三元运算符,但语法错误。

这样做:

angle[j][0] = (j == 0) ? 2 : (angle[j-1][0] + 3);

【讨论】:

  • @user12556559 如果我的回答对您有用,请考虑支持并接受我的回答
  • 但这不只是一个很好的 if-else 写法吗?我以为他想将 bool 语句用作数字,true 被转换为 1false 被转换为 0
  • @generic_opto_guy:这正是我所要求的。 Matlab 用户在这里。我觉得 C++ 太麻烦了。出于某种原因,我试图将我的 matlab 脚本转换为 C++。如果您有更好的建议,请帮助我。
  • @generic_opto_guy 我也有同样的感觉。在这种情况下,第一次迭代可以简单地从循环中解决,然后不需要分支。但是,如果一个人关心性能,他/她肯定不会用 array of arrays 来表示 2D 矩阵,而是使用 1D 数组。
  • @user12556559 如果您的要求与此答案不同,请不要接受。接受的答案意味着它回答了您的要求。
【解决方案2】:

线

angle[j][0] = (j == 0) * 2 + (j != 0) * (angle[j-1][0] + 3);

j0 时,您访问angle[-1] 时不起作用。这是未定义行为的原因。

查看您对另一个答案的评论,您显然正在寻找使用条件运算符。

angle[j][0] = (j == 0) ? 2 : (angle[j-1][0] + 3);

【讨论】:

    【解决方案3】:

    正如 Sahu 所说,您的组合线路的问题是您将 angle[j-1][0]j==0 结合使用,这是未定义的行为。这意味着实际上不可能将 if 和 else 部分组合成一个非分支语句。

    其次,这两个代码 sn-ps 看起来不同(三元/条件运算符产生的 C++ 代码行数更少):

        if (x == 1) 
            A = 7;
        else
            A = 13;
    

        A = (x == 1) ? 7 : 13;
    

    但它们编译为exactly the same machine code

    那么,我们如何解决您不想在每次循环迭代中都进行分支的问题?

    由于 test/branch 变量 (j) 也是循环变量,并且测试是针对 j == 0 的,这也是起始条件,您可以这样做:

    double** angle = new double* [10];   // for a 2D matrix
    
    angle[0] = new double[3];  // Prepare the first element
    angle[0][0] = 2;
    
    for (int j = 1; j < 10; j++)  // Fill out the rest
    {
        angle[j] = new double[3];
        angle[j][0] = angle[j - 1][0] + 3;
    
        std::cout << angle[j][0] << std::endl;
    }
    

    第一个元素的设置被移出循环,之后循环可以从j=1开始,并且循环体中只有else分支(当然没有测试)。

    但是,鉴于现代 CPU 中的分支预测器非常棒,并且您的循环恰好命中了 if-branch 一次;在第一次循环迭代和接下来的每个循环迭代中,我怀疑你会看到两个版本的执行时间有很大差异。因此,我只是建议您选择您认为最容易阅读和理解的版本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-28
      • 2016-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-10
      相关资源
      最近更新 更多