代码之家  ›  专栏  ›  技术社区  ›  Puppy

C++中无副作用的表达式

  •  6
  • Puppy  · 技术社区  · 14 年前

    我不明白的是,为什么像下面这样的程序是合法的?

    int main()
    { 
        static const int i = 0;
        i < i > i;
    }
    

    我是说,当然,没有人 有任何当前程序的表达式中没有副作用,因为这将是非常无意义的,它将使分析和编译语言更容易。那为什么不拒绝他们呢?允许使用这种语法实际上能给语言带来什么好处?

    int main() {
        static const int i = 0;
        int x = (i);
    }
    

    这种说法的实际好处是什么?

    还有最令人烦恼的分析。有人在其他函数中间声明函数吗?我是说,我们去掉了隐式函数声明之类的东西。为什么不为C++0X去掉它们呢?

    7 回复  |  直到 14 年前
        1
  •  4
  •   Steve Jessop    14 年前

    它将使解析和编译 语言容易多了

    我不知道怎么做。为什么更容易分析和编译 i < i > i 如果你是 必修的

    Java编译器禁止不可访问的代码(与没有影响的代码相反),这对程序员来说是一种混合的祝福,并且需要比编译器实际需要做的额外工作(基本块依赖性分析)。C++应该禁止不可达代码吗?可能不是。尽管C++编译器确实做了足够的优化来识别不可到达的基本块,但在某些情况下,它们可能做得太多。应该 if (foo) { ...} foo 是一个假编译时常量吗?如果它不是一个编译时常量,但是优化器已经知道如何计算该值,那么它是否合法,并且编译器必须意识到它删除它的原因是特定于实现的,以便不出错呢?更多特殊情况。

    实际上没有人有电流 它们的副作用

    荷载。例如,如果 NDEBUG assert 展开为无效表达式。所以编译器需要更多的特殊情况来允许 无用的表达,但不是其他的。

    我认为,其基本原理是,如果它扩展到了零,那么(a)编译器最终会对如下内容发出警告 if (foo) assert(bar); ,和(b)这样的代码在发行版中是合法的,但在调试中是不合法的,这很令人困惑:

    assert(foo) // oops, forgot the semi-colon
    foo.bar();
    

    像最令人烦恼的解析

    无论如何,现在太晚了。即使我们有一些巨大的洞察力,C++0X委员会已经错过了,为什么一些特性应该被移除或者不兼容地改变,他们不会在FCD中打破任何东西,除非FCD最终是错误的。

    请注意,对于所有的建议,任何编译器都可以发出警告(实际上,我不理解第二个例子中的问题是什么,但肯定是无用的表达式和函数体中的解析)。如果你是对的,没有人故意这样做,警告不会造成伤害。如果你错了,没有人故意这样做,那么你所说的删除它们的理由是不正确的。流行编译器中的警告可能会为删除某个功能铺平道路,特别是因为该标准主要由编译器编写者编写。事实上,我们并不总是收到这些事情的警告,这向我表明,它有比你想象的更多。

        2
  •  8
  •   Douglas Leeder    14 年前

    可能是因为禁止这样做会使规范更加复杂,这会使编译器更加复杂。

        3
  •  3
  •   Tony Delroy    14 年前
    • 有时将无用的语句放入程序中并编译它以确保它们是合法的(例如,所涉及的类型可以被解析/匹配等)是很方便的。

    • 特别是在生成的代码中(宏以及更复杂的外部机制、模板,其中策略或类型在某些非操作情况下可能引入无意义的扩展),有较少特殊的不可编译情况以避免使事情变得更简单

    • 可能有一些临时注释的代码删除了变量的有意义的用法,但是不得不类似地标识和注释所有在其他地方没有使用的变量可能会很痛苦。

    • C++需要一个很好的理由来向后(和保持C)兼容性。

        4
  •  0
  •   Oliver Charlesworth    14 年前

        5
  •  0
  •   Noe    14 年前

    作为C++标准的一个迭代,C++ 0x必须向后兼容。没有人可以断言,你写的声明不存在于某个关键软件中,比如说,NASA或国防部。

    不管怎样,关于你的第一个例子 分析器 不能断言 i 是一个静态常量表达式 i < i > i 是模板类型, 是“无效的变量声明”,不是“无用的计算”,仍然不是解析错误。

        6
  •  0
  •   Stilgar    14 年前

    可能是因为操作员超载而产生的副作用 cout<<i;

        7
  •  0
  •   AshleysBrain    14 年前

    没有副作用的表达式在模板化和宏代码中出现的频率可能比您想象的要高。如果你曾经声明 std::vector<int> ,您已经实例化了模板代码,没有任何副作用。 std::vector T . 在某些时候,这需要一个类似于 ptr->~T(); int 但是没有析构函数,所以调用没有副作用,将被优化器完全删除。它也可能在一个循环中,然后整个循环没有副作用,所以整个循环被优化器移除。

    std::向量<int> 不起作用 一个是。

    assert(a == b) . 在发布版本中,您希望这些断言消失,但不能将它们重新定义为空宏,否则语句如下 if (x) assert(a == b); 突然把下一个语句放到if语句中-一场灾难!在这种情况下 assert(x) ((void)0) ,这是一个没有副作用的语句。现在 if 语句在发布版本中也能正常工作-它什么也不做。