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

为什么C中不允许常量参数?

  •  95
  • Incognito  · 技术社区  · 15 年前

    它看起来很奇怪,尤其是C++开发人员。在C++中,我们用来标记一个参数 const 以确保其状态不会在方法中更改。还有其他C++特定的原因,比如通过 const ref 为了通过引用并确保状态不会更改。但是为什么我们不能在C中标记为方法参数const?

    为什么我不能像下面这样声明我的方法?

        ....
        static void TestMethod1(const MyClass val)
        {}
        ....
        static void TestMethod2(const int val)
        {}
        ....
    
    4 回复  |  直到 9 年前
        1
  •  56
  •   Eric Lippert    15 年前

    除了其他好的答案,我还要补充一个原因,为什么不把C样式的常量放入C中。你说:

    我们将参数标记为const,以确保在方法中不会更改其状态。

    如果警察真的这么做,那就太好了。警察不这么做。警察是个谎言!

    const并不能保证我能真正使用它。假设您有一个方法接受常量。有两个代码作者:编写 呼叫者 以及写 被叫者 . 被调用方的作者已使该方法采用常量。两位作者可以假设什么是对象的不变量?

    没有什么。被调用方可以释放const并改变对象,因此调用方没有 保证 调用一个接受常量的方法实际上不会改变它。类似地,被调用方不能假定对象的内容在被调用方的整个操作过程中都不会更改;被调用方可以在 非常量别名 而现在所谓的const对象 改变 .

    C-StyleConst不能保证对象不会更改,因此会被破坏。现在,C已经有了一个弱类型系统,如果你真的想做的话,可以把double重新解释成int,所以对于const来说,它也有一个弱类型系统并不奇怪。但是C被设计成 好的 类型系统,当你说“这个变量包含一个字符串”时,这个变量 实际上包含对字符串的引用 (或NULL)。我们绝对不想将C样式的“const”修饰符放入类型系统,因为 我们不希望类型系统是谎言 . 我们希望类型系统是 坚强的 这样你就可以 正确的理由 关于你的代码。

    C中的Const是 指南 它的基本意思是“你可以相信我,不要试图改变这件事”。那不应该在 类型系统 ;里面的东西 类型系统 应该是 事实 关于你可以推理的对象,而不是 指南 以其用途。

    现在,不要误会我;仅仅因为C中的const被深深破坏并不意味着整个概念都是无用的。我想看到的是一些 对的 有用的 C中“const”注释的形式,一种人类和编译器都可以用来帮助他们理解代码的注释,运行时可以用来执行自动并行化和其他高级优化等操作。

    例如,想象一下,如果你能在一大块代码周围“画一个方框”,然后说“我” 保证 这一大块代码不会以编译器可以检查的方式对此类的任何字段执行任何突变。或者画一个写着“这个”的方框 纯净的 方法会改变对象的内部状态,但不会以任何方式改变框外可见的状态”。这样的对象不能安全地自动多线程,但是 它可以自动记忆 . 我们可以在代码中添加各种有趣的注释,以实现丰富的优化和更深入的理解。 我们可以做得比弱的C样式const注释更好。

    然而,我强调这只是 投机 . 我们没有将这类特性应用到任何假设性的未来版本的C中的计划,如果有的话,我们也没有以这种或那种方式宣布。这是我很想看到的,也是未来对多核计算的强调可能需要的,但这些都不应该以任何方式被解释为对任何特定特性或未来方向的预测或保证。

    现在,如果您想要的仅仅是局部变量上的一个注释,这个参数表示“这个参数的值在整个方法中不会改变”,那么,当然,这很容易做到。我们可以支持将被初始化一次的“只读”局部变量和参数,以及在方法中更改的编译时错误。“using”语句声明的变量已经是这样一个局部变量;我们可以向所有局部变量和参数添加一个可选的注释,使它们像“using”变量一样工作。它从来不是一个非常高优先级的特性,所以它从未被实现。

        2
  •  23
  •   Ruben    15 年前

    为什么没有 const正确性 在C中是因为它不存在于运行时级别。记住,C 1.0没有任何功能,除非它是运行时的一部分。

    而clr没有const正确性概念的几个原因是:

    1. 它使运行时复杂化;此外,JVM也没有它,CLR基本上作为一个项目开始创建一个JVM类运行时,而不是一个类似C++的运行时。
    2. 如果在运行时级别有常量正确性,那么BCL中应该有常量正确性,否则就.NET框架而言,该特性几乎没有意义。
    3. 但是如果bcl需要const正确性,那么clr之上的每种语言都应该支持const正确性(vb、javascript、python、ruby、f_等),即 会发生的。

    const的正确性几乎只是C++语言中的一种语言特征。因此,这与为什么CLR不需要检查异常(即Java语言独有的特性)的讨论相同。

    另外,我认为在管理环境中引入这样一个基本类型的系统特性是不需要破坏向后兼容性的。所以不要指望进入C世界的常量正确性。

        3
  •  11
  •   Stephen Cleary    15 年前

    我认为C不正确有两个原因。

    第一个是 可理解性 . 很少有C++程序员理解常数的正确性。简单的例子 const int arg 很可爱,但我也见过 char * const * const arg -指向非常量字符的常量指针。函数指针上的常量正确性是一个全新的模糊层次。

    第二个原因是类参数是由值传递的引用。这意味着已经有两个等级的警察要处理,没有一个明显的明确 句法 . 类似的绊脚石是集合(和集合集合等)。

    const正确性是C++类型系统的重要组成部分。理论上,它可以作为只在编译时检查的内容添加到C中(它不需要添加到clr中,并且不会影响bcl,除非包含const-member方法的概念)。

    然而,我认为这是不太可能的:第二个原因(语法)将很难解决,这将使第一个原因(可理解性)更加成为一个问题。

        4
  •  5
  •   Pavel Minaev    15 年前

    const C语言中的“编译时间常数”,而不是C++中的“只读,但可能是其他代码可变的”。C++的粗略模拟 康斯特 在C是 readonly ,但那个只适用于字段。除此之外,C语言中还没有C++类的const正确性概念。

    基本原理是很难确定的,因为有很多潜在的原因,但我的猜测是希望首先保持语言的简单,以及实现第二种语言的不确定优势。

    推荐文章