const正确性如何帮助编写更好的程序?

时间:2009-04-13 09:38:37

标签: c# c++ const-correctness

这个问题来自C#问问C ++人员。 (我知道很多C,但只有一些C ++的一般知识)。

来到C#的大量C ++开发人员说他们错过了const正确性,这对我来说似乎很奇怪。在.Net中,为了禁止更改您需要创建具有只读属性/字段的不可变对象或对象,或者传递对象副本(默认情况下复制结构)。

C ++ const是否正确,是一种创建不可变/只读对象的机制,还是有更多的东西?如果目的是创建不可变/只读对象,那么在.Net等环境中也可以做同样的事情。

9 个答案:

答案 0 :(得分:13)

整篇文章专门讨论常见问题解答中的Const Correctness。享受!

答案 1 :(得分:7)

C ++中的const正确性只是一种确切地说出你的意思的方式:

void foo( const sometype & t ) {
   ...
}

说“我不会改变t提到的对象,如果我尝试,请Compiler先生警告我”。

它不是安全功能或(可靠地)创建只读对象的方式,因为使用C样式转换来破坏它是微不足道的。

答案 2 :(得分:6)

我敢打赌这是心态问题。我正在和很长时间的C ++人一起工作,并且注意到他们似乎用C ++思考(当然他们这样做了!)。他们需要一段时间才能开始看到他们熟悉的答案的多个答案,以获得像'正确'这样的'股票'答案。给他们时间,并尝试轻轻地教育他们。

话虽如此,我确实喜欢C ++'const'的保证方式。它主要是承诺接口的用户,对象,指针后面的数据或任何不会被搞乱的东西。我会将此视为const正确性的#1值。 #2值是编译器在优化方面可以允许的。

当然,问题是如果整个sw堆栈还没有从头开始构建const。

我确信C#有自己的一套范例来做同样的事情。这说明为什么“每年学习一门新的(计算或自然)语言”非常重要。只需要用心思其他方式来看世界,解决问题。

答案 3 :(得分:4)

使用const-correctness,您可以将可变对象公开为只读,而不会复制它并浪费宝贵的内存(尤其与集合相关)。我知道,桌面开发人员之间存在这种 CPU和内存便宜的理念,但它在嵌入式世界中仍然很重要。

最重要的是,如果在C ++中添加内存所有权的复杂性,最好不要复制包含或引用其他对象的非平凡对象,因此有一种方法将现有对象公开为只读

答案 4 :(得分:3)

优秀的Scott Meyer的书Effective C++专门针对这个问题编写了一个项目:

项目3:尽可能使用const。

它真的启发你: - )

答案 5 :(得分:3)

真正的答案,即使你没有使用它真的很难掌握,你的表现力也会失去。该语言具有您无法在C#中表达的概念,它们具有意义,它们是设计的一部分,但在代码转换中丢失了。

这不是答案,而是一个例子:

请考虑您有一个容器,该容器按存储的元素的字段进行排序。那些对象真的很大。您需要为读者提供对数据的访问权限(考虑在UI中显示信息)。

现在,在C#/ Java中,您可以采用以下两种方式之一:为要使用的调用者制作副本(保证数据不会更改,但效率低下),或者返回对内部持有的引用对象(只希望调用者不会通过setter更改您的数据)。

如果用户获取引用并通过它更改了作为索引的字段,那么容器不变量就会被破坏。

在C ++中,您可以返回一个常量引用/指针,编译器将在您返回的实例上禁用调用setter方法(变异方法)。您将获得用户不会更改的安全性(*)和通话效率。

之前未提及的第三个选项是使对象不可变,但是在任何地方都禁用了更改。将不允许对对象进行完全控制的更改,并且唯一可能的更改是创建一个包含所执行更改的新元素。这相当于时间和空间。

答案 6 :(得分:2)

C ++提供了很多方法可以搞砸你的代码。我认为const正确性是将约束置于代码中的第一种有效方式,以便控制“副作用”(不需要的改变)。

将参数标记为const(通常引用const对象或指向const对象的指针),将确保无法更改传递的对象,因此您没有该函数/方法的“副作用”。

将方法标记为const将保证该方法不会更改其使用的对象的状态。如果是,编译器将生成错误。

标记const数据成员将确保数据成员只能在构造函数的初始化列表中初始化,并且无法更改。

此外,智能编译器可以使用constness作为各种性能优化的提示。

当然,你可以覆盖constness。 Constness是编译时检查。默认情况下,您不能破坏规则,但是您可以使用强制转换(例如const_cast)使const对象成为非const,以便可以更改它。

答案 7 :(得分:1)

在编写代码时,只需征求编译器的帮助就足以提倡const-correctness。但是今天还有一个额外的优势:当你知道我们的对象在哪里可以改变以及它们不能改变的地方时,多线程代码通常更容易编写。

答案 8 :(得分:1)

我认为很遗憾C#不像C ++那样支持const正确性。我传递给函数的所有参数中有95%是常量值,const函数保证在调用后不会修改通过引用传递的数据。 “const”关键字提供了编译器检查的文档,这对大型程序有很大帮助。