C++;const关键字-自由使用? 以下C++函数: void MyFunction(int age, House &purchased_house) { ... } void MyFunction(const int age, House &purchased_house) { ... }
哪个更好 在这两种情况下,“年龄”都是通过值传递的。我想知道‘const’关键字是否必要:它对我来说似乎是多余的,但也很有用(作为一个额外的指示,变量不会改变)C++;const关键字-自由使用? 以下C++函数: void MyFunction(int age, House &purchased_house) { ... } void MyFunction(const int age, House &purchased_house) { ... },c++,syntax,constants,C++,Syntax,Constants,哪个更好 在这两种情况下,“年龄”都是通过值传递的。我想知道‘const’关键字是否必要:它对我来说似乎是多余的,但也很有用(作为一个额外的指示,变量不会改变) 是否有人对以上哪种(如果有的话)更好有任何意见?关于这一点,请参见Meyers和“有效的C++”,并自由地使用const,尤其是在传递引用语义方面 在这种原子变量的情况下,效率并不重要,但代码清晰性仍然有好处。您不仅表示它不会更改,还会阻止代码认为它可以更改,并且会在编译时捕获它。首先,它只是一个实现细节,如果您将const放在那里,不
是否有人对以上哪种(如果有的话)更好有任何意见?关于这一点,请参见Meyers和“有效的C++”,并自由地使用const,尤其是在传递引用语义方面
在这种原子变量的情况下,效率并不重要,但代码清晰性仍然有好处。您不仅表示它不会更改,还会阻止代码认为它可以更改,并且会在编译时捕获它。首先,它只是一个实现细节,如果您将const放在那里,不要把它放在声明集中(标题)。仅将其放在实现文件中:
// header
void MyFunction(int age, House &purchased_house);
// .cpp file
void MyFunction(const int age, House &purchased_house);
{
...
}
参数在定义中是否为常量纯粹是一个实现细节,不应该是接口的一部分
我不经常看到这种事情,我也不这样做。拥有参数const比帮助更容易让我困惑,因为我会立即将其模式匹配为“const int&age”:(当然,这与在另一个级别拥有const完全不同:
// const is a *good* thing here, and should not be removed,
// and it is part of the interface
void MyFunction(const string &name, House &purchased_house);
{
...
}
在这种情况下,const将影响函数是否可以更改调用方的参数。在这个意义上的const应该尽可能多地使用,因为它可以帮助确保程序的正确性和改进代码的自我记录。
使用<代码> const <代码>的一个好处是您不能在foo.process(++age)这样的代码回收
;age
void print(int number);
实际上与此相同:
void print(int const number);
因此,对于编译器来说,声明函数的方式没有区别,并且不能通过将const关键字放在pass-by-value参数前面来重载函数
进一步阅读Herb Sutter的建议:
“避免在函数声明中使用常量传递值参数。如果不修改参数,则仍在同一函数的定义中使用常量。”
他建议避免以下情况:
void print(int const number);
因为常量是混乱的、冗长的和冗余的
但是在定义中,您应该这样做(如果您不更改参数):
因此,您可以确保,即使在函数体的1000行之后,也始终保持该数字不变。编译器将禁止您将该数字作为非常量引用传递给另一个函数。这是过度使用。
当你说‘const int age,…’时,你实际上说的是“你甚至不能更改函数中的本地副本”。你所做的实际上是当程序员想要更改age/通过非const引用传递时,强迫他使用另一个本地副本,从而降低程序员代码的可读性
任何程序员都应该熟悉按引用传递和按值传递之间的区别,就像任何程序员都应该理解“const”一样。拥有一个按值const传递的原语类型是毫无价值的。将const传递给函数通常是很有用的,因为它是与调用方的契约,函数不会改变在这种情况下,因为int是通过值传递的,所以函数不能进行任何在函数外部可见的更改
另一方面,如果对象没有任何更改,引用和非平凡对象类型应该始终使用const。理论上,这可能会允许进行一些优化,但最大的好处是我上面提到的契约。当然,缺点是,它可以使您的接口更大,const是一件困难的事情改装到现有系统中(或使用不在任何地方使用const的第三方API)正如其他人已经说过的,从C++语言的观点看,上面的代码> const 对函数签名没有影响,即函数类型是否保持不变,而不管<代码> const < /C>是否存在。C++抽象语言的唯一影响是不能修改这个参数。r位于函数体内部
但是,在较低的层次上,对于一个足够聪明的编译器,应用于参数值的<代码> const 修饰符可以有一些优化的好处。考虑两个具有相同参数集的函数(为简单起见)
假设在代码中的某个地方,它们被调用如下foo(x, d, m);
bar(x, d, m);
通常,编译器在调用函数之前会准备带有参数的堆栈框架。在这种情况下,堆栈通常会准备两次:每次调用一次。但聪明的编译器可能会意识到,因为这些函数不会更改其局部参数值(用常量声明),为第一次调用准备的参数集可以安全地重新用于第二次调用。因此,它只能准备堆栈一次
这是一种非常罕见且晦涩难懂的优化,它只能在调用时(相同的翻译单元或高级全局优化编译器)已知函数定义时才能工作,但有时可能值得一提
说它“毫无价值”或“没有效果”是不正确的,即使对于一个典型的编译器来说这是错误的
int foo(const int a, const double b, const long c) {
/* whatever */
}
void bar(const int a, const double b, const long c) {
/* whatever */
}
foo(x, d, m);
bar(x, d, m);
const int age_last_year = age - YEAR;
void MyFunction(const int age, House &purchased_house)
{
const int age_last_year = age - YEAR;
}
void MyFunction(int age, House &purchased_house)
{
int age_last_year = age - YEAR;
}
void WriteSequence(int const *, const int);
int main()
{
int Array[] = { 2, 3, 4, 10, 12 };
WriteSequence(Array, 5);
}
#include <iostream>
using std::cout;
using std::endl;
void WriteSequence(int const *Array, const int MAX)
{
for (int const * i = Array; i != Array + MAX; ++i)
cout << *i << endl;
}
void WriteSequence(int Array[], int MAX)
{
MAX += MAX;
for (int * i = Array; i != Array + MAX; ++i)
cout << *i << endl;
}