这个问题来自C#问问C ++人员。 (我知道很多C,但只有一些C ++的一般知识)。
来到C#的大量C ++开发人员说他们错过了const正确性,这对我来说似乎很奇怪。在.Net中,为了禁止更改您需要创建具有只读属性/字段的不可变对象或对象,或者传递对象副本(默认情况下复制结构)。
C ++ const是否正确,是一种创建不可变/只读对象的机制,还是有更多的东西?如果目的是创建不可变/只读对象,那么在.Net等环境中也可以做同样的事情。
答案 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)
答案 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”关键字提供了编译器检查的文档,这对大型程序有很大帮助。