如果你已经知道variables应该是常量,为什么你会使用关键字const?
我正在阅读的很多书籍都使用关键字const
时,不应该修改variables的值。 除了向代码读者指定如果您修改此variables(您可以使用注释执行此操作),您可能会导致错误,为什么您需要该关键字成为任何编程语言的一部分? 在我看来,如果你不想要一个variables修改,根本就不要。
有人能为我澄清这个吗?
除了向读者指定可能会导致错误的代码,如果您修改此variables(您可以使用注释来执行此操作)
不是“可以”; 会在你的程序中造成错误。
- C ++编译器将通过编译失败和诊断消息(“编译器错误”)来执行它,而不需要注释。
- AC编译器会强制执行它,尽pipe它的标准库有一些遗留的问题,比如
strchr
,并且它有一些相当宽松的隐式转换规则,可以让你很容易地删除const
。 但是,仅仅因为你编译成功并不意味着你没有错误; 不幸的是,这确实意味着错误可能是程序中的微妙错误,以及巨大而壮观的崩溃。
无论哪种方式,你的程序保证在其中包含一个错误 。
在我看来,如果你不想要一个variables修改,根本就不要。
那么这一切都很好,但没有人是完美的。 程序员犯错误。 这允许编译器 – 永远不会犯错误(至less,通常不会) – 把它们指向你。
当你使用一些数据variables的时候,这个特殊的用法会在创build的地方远离许多代码行。 离得越远,修改它越容易,而不会意识到你不应该这样做。 对于庞大而复杂的代码库,这只是一个必须。
你在代码库中获得了可测性 , 正确性和稳定性的一个新的度量标准,以及一个真正微妙和令人讨厌的错误的可能原因。 当编译器知道某些值在编译之后不会改变的时候,你的编译器也有很多优化的机会 (在某些情况下)。
我们可以整天列出好处,但是,直到您完成这样的代码库之后,您才会完全明白它的优点。
事实上,在一个完美的世界中, 所有的variables默认都是const
的 ,你需要用关键字mutable
声明它们才能改变它们。 C ++是向后的。
至less在C ++中, const
除了把你的意图logging到其他程序员之外,还有一些用处。
const
也可以告诉编译器一些东西。 例如,一个需要引用的函数,如: void f(T &t);
不能接受一个临时对象作为它的参数。 要做到这一点,你需要const
限定参考,如: void f(T const &t)
。
同样,为了调用const对象的成员函数,成员函数必须是const
限定的: void T::foo() const {}
。
在embedded式系统中, const
可能意味着更多,可能会告诉编译器在哪里find有问题的对象(把它放在ROM和RAM中)。 const
本身并不足以告诉它“把这个对象放在ROM中”,但它往往是一个先决条件。
同样(在C ++ 11下) const
告诉编译器有关线程的安全性 。
现在,毫无疑问,你可以定义一些其他语言(在其他方面)与C或C ++有些相似之处,这些语言在这些方面没有使用const
。 结果将是一个相当不同的语言,但任何一个。 如果不知道自己的意图,就不可能说出结果如何,但最终可能会更接近于Java或C#(对于几个例子),这两种方法在某些方面与C和C ++有一些相似之处,但不是特定的一个(即,不要像C和C ++那样使用const
)。
除了在其他答案中已经讨论过的编程方面的一些常见问题之外,有一件事情是我的态度:
在我看来,如果你不想要一个variables修改,根本不。
一般的经验法则是20%的编写代码花费在开发阶段。 另外80%是在代码升级,维护等方面花费了一辈子的时间。这意味着许多其他人将在你自己的代码上工作。
在发展过程中花费的时间避免了多年后的问题,这是一个很好的投 这项工作包括:撰写评论; 定义常量常量; 并编写不依赖于模糊语言结构的显式代码。
另外,@ worlboss,我听到相当的不容忍。 正如其他一些人所说,碳单位犯了错误,硅单位可以做的任何事情,以帮助避免错误是值得赞赏的。
它告诉编译器该variables不应该被修改,所以如果有人编写修改它的代码,编译器将其标记为错误。
两个原因:
- 编译器强制执行文档
- 编译器优化
伊恩·兰斯·泰勒(伊恩·兰斯·泰勒(Ian Lance Taylor)(曾在gcc
和gold
连接器上工作过)
const的第一个含义对程序有实际的影响。 一个声明为const的variables可能与一个未声明为const的variables编译不同。
另一方面,const的第二个含义是编译器强制执行的文档。 如果尝试使用const限定指针更改值,则编译器将发出错误,但声明这样的指针不会更改生成的代码。
这里是一个简单的C例子:
void PrintList(const struct List *l); void SortList(struct List *l); int CmpList(const struct List *a, const struct List *b); void AppendList(struct List *l, struct List *m); void PushList(struct List *l, struct ListNode *n); void PopList(struct List *l, struct ListNode *n);
在这里,我们有一小部分function与一些节点列表一起工作。 首先,即使不知道函数的名称,我们可以立即看到哪些函数以某种方式改变了我们的列表,哪些函数不改变我们的列表。 const
函数就像标准库一样,不会改变你的数据,也不允许你用它们来改变你的数据。 C编译器试图保持强制指针的const
到传递给函数的数据。 所以在这种情况下,我可以合理地确定,比较两个列表并不是在执行运行时debugging时将它们改变的function,因为我已经保护自己免受对数据的意外修改。 ;)
你的编译器可以做很大的优化,知道一个variables不会被改变:不是将它存储在内存中,而是直接写入可执行操作码。
例如:你有一个和B,你想添加他们,你做一个+ B。 如果你声明一个常量和值为3,程序会改为3 + b,这将节省内存和循环,因为它不需要检索一个值。
问题是你的编译器不能预先知道variables是否是常量,当然它可以分析整个代码,并检查你是否修改了这些variables,但是不是100%肯定的,因为将来的代码也可以修改它。
关键字const
对团队和长期项目非常有用。 我会给你几个例子,那些应该解释const
关键字的值。
可以说,现在我正在创build将用于进一步项目的lib。 所以这意味着今天编写的代码在几年之后需要被信任,在这样的一段时间内,我可能会忘记哪个variables不应该被修改(同事甚至不知道什么可以被修改,哪些不能被修改)。 所以这个简短的例子解释了为什么要使用const
。
谈论评论时,截止date即将到来,还有很多东西还没有正常工作,对每个function的评论只是浪费时间。 但在某些情况下,评论是必须的,因为第一个问题(截止date)的评论可能不会被阅读,因为大多数评论是无用的,但重要的评论也会被忽略。 所以最好使用const
关键字,这会给编译错误带来麻烦,然后编写和阅读大量的注释。
这是一个很难回答的问题,因为国际海事组织是基于信仰的。 其中一个信念是,你可以保护你的代码免受某种改变,只是添加更多的代码。 当然,编译器使用额外的代码来检查一切正常。
我认为这并不总是正确的,你不能保护你的代码对抗你自己或你的开发团队只是添加关键字,事实上有很多语言没有任何常量,公共,私有,保护,内部,整型,浮点型,双关键字,这并不意味着他们不是好的语言。
一些代码模式也是如此,为什么人们浪费了很多时间来讨论单例呢? 如果你只想要一个实例,你只需要创build一个实例就可以了。 同样的思维方式无处不在,看看10年前发布的防御性编程文章,再一次用代码保护代码的想法。
在某些方面,你必须决定在哪里设置责任,在开发者手上还是在编译器上。 然而,无论是编译器还是其他工具都不能将代码保存在开发人员的手中,因此大量的关键字毫无价值,或者只是一种与其他开发人员进行交stream的方式。
常量variables只是让你写更多的可读代码。
在几乎所有的语言中最常用的是允许我们使用名称来引用常量值,所以你可以用stream利的语言告诉别人这个名字是指什么,而不需要在代码中传播注释,节省时间和读者了解参数的参数types和特性。 当然,如果你的常量在你的代码中被重用,你也会受益匪浅。 好吧,像这样的代码可以更具可读性:
processPages(LETTER_PAPER_WIDTH, LETTER_PAPER_HEIGHT);
…比这个:
processPages(215.9, 279.4); // 8.5 x 11 Inches in millimeters for Letter Papers
在上面的例子中,你需要了解每个参数是什么,它的单位和types来解释这些值,你还需要根据评论来validation它,因为这样的冗余评论(那些重播什么的评论)是不是一个可靠和如此有用的评论(根据清洁代码中的罗伯特·马丁: http : //goo.gl/5EyY是一个糟糕的评论)。
考虑一下你在整个项目中多次使用相同的常量的场景,而且你在所有的地方都用硬编码。 现在突然间,你需要将常量的值改为另一个值,所以在所有的位置进行改变都是非常紧迫的。
所以我认为让你的代码更可维护绝对是其中的一个原因。