【问题标题】:C++ Conditional operator with different types as arguments具有不同类型作为参数的 C++ 条件运算符
【发布时间】:2013-05-23 13:25:19
【问题描述】:

我正在尝试在 int 和 *node(节点是自定义结构)上使用条件运算符 (?)。这是我的代码,以及由此产生的错误。

节点:

struct node {
  int num;
  node *next;
};

条件执行:

void PrintNodes(node *head_p) {
  int done = 0;
  while (!done) {
    PrintNodeData(head_p);
    // if (head_p->next==NULL) {
    //   done++;
    // } else {
    //   head_p++;
    // }
    ((head_p->next==NULL) ? done : head_p)++;
  }
}

我在条件语句上方的 cmets 中有等效的 if...then...else 语句,我只是希望能够将其修剪为一行。

编辑

错误:

test.cc: In function ‘void PrintNodes(node*)’:
test.cc:28:36: error: operands to ?: have different types ‘int’ and ‘node*’
make: *** [all] Error 1

【问题讨论】:

  • 而产生的错误是...?
  • 为什么你想把它剪成一行?
  • 这很丑,想想更好的办法
  • 因为我喜欢小而简单的功能,而且我认为它不会让它太难以阅读。
  • @JShoe 你错了。

标签: c++ pointers conditional-operator


【解决方案1】:

别这样。做明确的事情。

长答案是 C++ 有一个类型系统,而你试图做的事情违反了它。

【讨论】:

    【解决方案2】:

    我在条件语句上方的 cmets 中有等效的 if...then...else 语句,我只是希望能够将其修剪为一行。

    不要这样做。首先,因为它使您的代码不必要地难以阅读。其次,因为条件运算符中的两个表达式的类型都不能转换为另一个表达式的类型。

    根据 C++11 标准的第 5.16/3 段:

    [...] 如果第二个和第三个操作数有不同的类型并且有(可能是 cv 限定的)类 类型,或者如果两者都是相同值类别和相同类型(除了 cv 限定)的泛左值,则 尝试将这些操作数中的每一个转换为另一个的类型。 [...]

    【讨论】:

      【解决方案3】:

      你不能这样做!条件运算符需要两个具有相同类型或“兼容”类型的操作数(即,一个可以隐式转换为另一个)。但是这里你的操作数是int和node*类型(而且你试图将结果用作++的左值,所以我们可以说类型是int&和node*&),不兼容。

      另外,为什么不简单地这样做呢?

      void PrintNodes(node *head_p) {
        while (head_p) {
          PrintNodeData(head_p);
          head_p = head_p->next;  // was: head_p++;
        }
      }
      

      【讨论】:

      • 因为那样它会无限消耗我所有的内存并尝试打印不存在的节点。
      • 我用head_p = head_p->next替换了head_p++
      • 啊!这真是太棒了,我知道在我的循环中有一些我没有想到的东西。谢谢!
      【解决方案4】:

      我会使用 bool,而不是使用 ++ 将其设置为 true:

      void PrintNodes(node *head_p) {
        bool done = false;
        while (!done) {
          PrintNodeData(head_p);
          if (head_p->next==NULL)) done = true;
          else head_p++;
        }
      }
      

      虽然head_p++ 不应该是head_p= head_p-next?

      当然,除非您参加的是混淆代码竞赛,在这种情况下,这将是一个不错的选择:

      void PrintNodes(node *head_p) {
        node* done = nullptr;
        while (!done) {
          PrintNodeData(head_p);
          ((head_p->next==NULL) ? done : head_p)++;
        }
      }
      

      【讨论】:

      • 这也很容易。我没有发现任何区别。
      • 您的评论评论的是哪一部分?除非有node* operator++(const node *x) { return x->next; },否则head_p++; 与head_p = head_p->next; 不同[除非这是通过对象数组分配节点的特殊情况——但这不完全是链表或类似的东西......跨度>
      • 是的,但不要仅仅因为你可以这样做。编程中有一条关于“没有惊喜”的规则。坚持对有意义的类/结构这样做——如果你实现自己的大数字类、列表的迭代器类或类似的。但不仅仅是“因为我可以”。
      猜你喜欢
      • 1970-01-01
      • 2013-06-13
      • 2020-05-01
      • 2015-05-24
      • 2015-03-27
      • 1970-01-01
      • 1970-01-01
      • 2016-08-30
      • 1970-01-01
      相关资源
      最近更新 更多