【问题标题】:Increment a variable in C++ with a void function使用 void 函数增加 C++ 中的变量
【发布时间】:2020-08-21 10:00:05
【问题描述】:

我想让我的代码更简洁,所以我写了这个:

while(m <= r) 
    nums[m] ? nums[m] == 1 ? m++ : swap(nums[m], nums[r--]) : swap(nums[m++], nums[l++]);

但它不起作用,因为 'swap' 是一个 void 函数,但 'm++' 返回 int。 (“? 的右操作数为 void,但左操作数的类型为 int”错误)。所以我想知道如何替换 m++ 使其为 void 类型。

我知道我可以创建一个新的 void 函数(例如 void increase(int &x){x++;}),但我想将我的代码保留为单行。

我制作的最佳工作变体是“swap(nums[m], nums[m++])”,它对我的​​数组没有任何作用,但它看起来很糟糕。我还可以使用哪些其他功能?

【问题讨论】:

  • (void) 的简单转换可以解决您的问题:demo on coliru。不过整个表情看起来有点吓人……
  • .... arrr ...简洁并不总是意味着更好。总是更喜欢可读性。这段代码将无法通过任何体面的代码审查,即使它可以编译。
  • @Scheff:我认为在swap 之后使用operator , 也返回int 会更吓人;)
  • 你担心错了。这段代码绝对不可读,更糟糕的是,无法维护。它应该用if 语句重写。
  • 这完全是对三元运算符的滥用。这并不是要替换 if 语句,而是要在两个值之间进行选择。

标签: c++


【解决方案1】:

我想让我的代码更简洁

将许多副作用烘焙到嵌套非括号三元运算符的单个表达式中(利用隐式转换为 bool)确实会使您的代码更复杂、更容易出错并且可能隐藏事实原来的代码实际上应该被分解并重新分解成更简单的东西。

为什么不提倡清晰而不是过于复杂的简洁呢?例如。从直接的方法开始:

while(m <= r) {
    if (nums[m] != 0) {
        if (nums[m] == 1) {
            ++m;
        }
        else {
            swap(nums[m], nums[r--]); 
        }
    }
    else {
        swap(nums[m++], nums[l++]);
    }
}

可以重新分解为:

while(m <= r) {
    if (nums[m] != 0) {
        if (nums[m] == 1) {
            ++m;
        }
        else {
            swap(nums[m], nums[r]); 
            --r;
        }
    }
    else {
        swap(nums[m], nums[l]);
        ++m;
        ++l;
    }
}

可以重新分解为:

while(m <= r) {
    const std::size_t swap_from_idx = m;
    std::size_t swap_with_idx = m;  // default: no swapping.

    if (nums[m] == 1) {
        ++m;
        continue;
    }
    else if (nums[m] == 0) {
        swap_with_idx = l;
        ++l;
    }
    else {
        swap_with_idx = r;
        --r;
        ++m;
    }
    swap(nums[swap_from_idx], nums[swap_with_idx]);
}

或例如:

while(m <= r) {
    // No swapping.
    if (nums[m] == 1) {
        ++m;
    }
    // Swapping.
    else {
        const std::size_t swap_from_idx = m;
        std::size_t swap_with_idx = l;
        
        if (nums[m] == 0) {
            ++l;
        }
        else {
            swap_with_idx = r;
            --r;
            ++m;
        }
        swap(nums[swap_from_idx], nums[swap_with_idx]);
    }
}

此时您可能会问自己,原始循环设计是否过于复杂,和/或是否应该将循环体的一部分分解为单独的实用函数。


如果您的if/else if/else 逻辑达到了过高的圈复杂度,则很少尝试通过高度复杂的三元运算符表达式来隐藏它,而是通过重构并在适用的情况下将某些部分分解为单独的功能。

【讨论】:

  • 是的,谢谢。我最初也是这样做的。我只是遇到了一个挑战,要把它写成一个衬里。
【解决方案2】:

如果你想让表达式m++ 有副作用,并且有一个void 类型,你可以像这样简单地转换表达式:

(void)m++

它将首先评估m++,然后将其转换为void

这是demo

【讨论】:

  • 哇,就是这么简单。 C++ 真的很棒。我发现你也可以把它写成 void(m++)。我觉得这个更好看。
  • @BregaStanislav 是的,它们都是等价的。选择哪个看起来更好:) 确保阅读其他答案中的建议以及有关您的代码的建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-23
  • 2018-07-27
  • 1970-01-01
  • 2017-06-14
  • 1970-01-01
相关资源
最近更新 更多