如果你已经知道变量应该是常数,为什么要使用关键字const?

Fut*_*Sci 68 c c++ const keyword

我正在阅读的许多书籍const在不应修改变量值时使用关键字.除了向代码的读者指定如果修改此变量可能会导致错误(您可以使用注释来执行此操作),为什么您需要将该关键字作为任何编程语言的一部分?在我看来,如果你不想修改变量,根本就不要.

有人可以为我澄清一下吗?

Lig*_*ica 98

除了向代码的读者指定修改此变量可能导致错误(您可以使用注释执行此操作)

不是"可能"; 导致你的程序出错.

  • C++编译器会使用编译失败和诊断消息("编译器错误")强制执行它,而不需要注释;
  • AC编译器将在大多数情况下强制执行它,尽管它的标准库由于遗留问题而有漏洞,例如strchr,它有一些相当宽松的隐式转换规则,可以让你放弃const而不会很容易地意识到它.但是,仅仅因为你有一个成功的编译并不意味着你没有错误; 不幸的是,它确实意味着错误可能是你的程序中的微妙错误,以及大而壮观的崩溃.

无论哪种方式,您的程序都保证在其中包含错误.

在我看来,如果你不想修改变量,根本就不要.

嗯,这一切都很好,但没有人是完美的.程序员犯错误.这允许编译器 - 它从不会出错(至少通常不会) - 指出它们.

当你使用一些数据变量时,它会特别有用,它可以创建多少行代码.它越远,就越容易修改它而不会意识到你不应该这样做.对于大型,复杂的代码库,它只是必须的.

您可以在代码库中获得可证明性,正确性稳定性的新度量,以及可能导致真正微妙和令人讨厌的错误的大部分内容.当编译器知道某些值在编译后不会改变时,编译器(在某些情况下)也有很多优化机会.

我们可以整天列出优势,但实际上,在你使用这样的代码库之前,你不会完全理解它.

事实上,在一个完美的世界中,所有变量都是const默认的,你需要用关键字声明它们mutable才能更改它们.C++是倒退的.

  • "在一个完美的世界中,所有变量默认都是const":他们不会被称为不变量吗? (21认同)
  • @ouah:Scala不是那么完美的世界.它鼓励不变性.Haskell(例如)强制执行它. (20认同)
  • 我想生活在那个完美的世界! (17认同)
  • +1.在经历了Haskell和并发编程之后,我得出了相同的结论*"默认情况下所有变量都是const"*.事实上,如果变量是*mutable***,那么它在哲学上是不健全的**.如果一个类的成员默认为公共*,它具有相同的哲学问题*. (2认同)

Jer*_*fin 40

至少在C++中,const除了将您的意图记录到其他程序员之外,还有一些用途.

const也可以告诉编译器一些东西.例如,一个带引用的函数,如:void f(T &t);不能接受临时对象作为其参数.要实现这一目标,您需要对const参考进行限定,例如:void f(T const &t).

同样,要在const对象上调用成员函数,成员函数必须const限定为:void T::foo() const {}.

在嵌入式系统中,const 可能意味着更多,可能告诉编译器在哪里找到有问题的对象(将它放在ROM与RAM中).const它本身并不足以告诉它"把这个对象放在ROM中",但它仍然是一个先决条件.

同样(在C++ 11下)const 告诉编译器线程安全性.

现在,毫无疑问,您可以定义一些其他语言(在其他方面)与C或C++有某些相似之处,而const这些语言并没有以这些方式使用.结果将是与任何一种语言截然不同的语言.在不知道你的意图的情况下,不可能说它会如何发展,但最终可能会更接近Java或C#(有几个例子),这两者在某些方面都与C和C++有些相似,但不是这个特别的一个(即,不要const像C和C++一样使用).


Jac*_*man 37

除了在其他答案中已经讨论过的通常的编程注意事项,我关注的一点是态度:

在我看来,如果你不想修改变量,根本就不要.

一般的经验法则是,编写代码的成本的20%用于开发阶段.另外80%是在代码的生命周期内进行升级,维护它等等.这意味着除了你自己以外,很多其他人都会使用你的代码.

在开发过程中花费数年时间避免问题的时间是一项很好的投资.这项工作包括:撰写评论; 定义常量常量; 并编写依赖于模糊语言结构的显式代码.

另外,@ worlboss,我听到了相当多的不宽容.正如其他一些人评论的那样,碳单位会犯错误,而硅单位可以做的任何事情都可以帮助避免错误.

  • 提及大多数人忘记的80%的维护费用+1. (9认同)

edt*_*guy 21

它告诉编译器不应修改变量,因此如果有人编写修改它的代码,编译器会将其标记为错误.

  • 我敢打赌,在这个问题出现时,与绩效相关的好处也非常重要. (2认同)

oua*_*uah 17

两个原因:

  1. 编译器强制文档
  2. 编译器优化

以下是来自Ian Lance Taylor(他的工作和链接器)的一个很好的解释:gccgold

const的第一个含义对程序有实际影响.声明为const的变量可以与未声明为const的变量进行不同的编译.

另一方面,const的第二个含义实际上是编译器强制的文档.如果尝试使用const限定指针更改值,编译器将发出错误,但声明此类指针不会更改生成的代码.

  • `[C++ 11:8.3.5/3]:`_ [..] _生成参数类型列表后,**在形成函数类型时删除修改参数类型的任何顶级_cv-qualifiers_**._ [..] _ (3认同)

Cyb*_*ull 6

这是一个简单的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);
Run Code Online (Sandbox Code Playgroud)

这里我们有一小组函数可以使用某种节点列表.首先,我们甚至不知道函数的名称,我们可以立即看到哪些函数以某种方式改变了我们的列表,哪些函数没有.这些const函数与标准库中的函数不同,它们不会更改您的数据,也不允许您使用它们更改数据.C编译器会尝试const将指针的强度保持为传递给函数的数据.因此,在这种情况下,我可以合理地确定比较两个列表不是在我进行运行时调试时将它们修改的函数,因为我保护自己免受意外修改我的数据.;)


jok*_*oon 5

您的编译器可以进行大的优化,知道变量不会被更改:不是将其存储在内存中,而是直接写入可执行操作码.

例如:你有a和b,你想要添加它们,你做a + b.如果声明a为const且值为3,则程序将生成3 + b,这将节省内存和周期,因为它不需要检索值.

问题是你的编译器不能事先知道变量是否是常量,当然它可以分析整个代码并检查你是否修改了这些变量,但它不是100%肯定,因为未来的代码也可以修改它.