在以下C++函数中:
void MyFunction(int age, House &purchased_house)
{
...
}
void MyFunction(const int age, House &purchased_house)
{
...
}
Run Code Online (Sandbox Code Playgroud)
哪个更好?
在两者中,'年龄'都是按价值传递的.我想知道'const'关键字是否有必要:对我来说似乎是多余的,但也很有用(作为额外的指示,变量不会改变).
有没有人对上述哪个(如果有的话)更好有任何意见?
Joh*_*itb 65
首先,它只是一个实现细节,如果你把const放在那里,不要把它放在声明集(标题)中.只将它放在实现文件中:
// header
void MyFunction(int age, House &purchased_house);
// .cpp file
void MyFunction(const int age, House &purchased_house);
{
...
}
Run Code Online (Sandbox Code Playgroud)
参数在定义中是否为const纯粹是一个实现细节,不应该是接口的一部分.
我经常没见过这种事,我也不这样做.使用参数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);
{
...
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,const将影响函数是否可以更改调用者的参数.应尽可能经常使用此意义的Const,因为它可以帮助确保程序的正确性并改进代码的自我记录.
Van*_*uan 43
我建议阅读Herb Sutter.特殊的C++.有一章"Const-Correctness".
"事实上,对于编译器,无论是否在值参数前面包含此const,函数签名都是相同的."
这意味着这个签名
void print(int number);
Run Code Online (Sandbox Code Playgroud)
实际上与此相同:
void print(int const number);
Run Code Online (Sandbox Code Playgroud)
因此,对于编译器,如何声明函数没有区别.并且你不能通过将const关键字放在pass by value参数前面来重载它.
进一步阅读,Herb Sutter建议:
"避免在函数声明中使用const值传递参数.如果不修改参数const,则仍然将参数const置于同一函数的定义中."
他建议避免这种情况:
void print(int const number);
Run Code Online (Sandbox Code Playgroud)
因为那个const令人困惑,冗长和多余.
但在定义中,您应该这样做(如果您不更改参数):
void print(int const number)
{
// I don't want to change the number accidentally here
...
}
Run Code Online (Sandbox Code Playgroud)
所以,你会确信即使在1000行函数的主体之后你总是没有触及数字.编译器将禁止您将该数字作为非const引用传递给另一个函数.
Ore*_*n S 22
恕我直言,这是过度使用.当你说'const int age,...'时你实际上说的是"你甚至不能改变你职能中的本地副本".你所做的实际上是通过强迫他在他想要改变年龄/通过非const引用传递它时使用另一个本地副本来降低程序员代码的可读性.
任何程序员都应该熟悉传递引用和传递值之间的区别,就像任何程序员应该理解'const'一样.
请参阅Meyers和'Effective C++',并使用const自由,特别是使用pass-by-reference语义.
在这种原子变量的情况下,效率无关紧要,但代码清晰度仍然有益.
好吧,正如其他人已经说过的那样,从C++语言的角度来看,上面对const函数签名没有影响,即函数类型保持不变,无论是否const存在.它在抽象C++语言级别上唯一的影响是你不能在函数体内修改这个参数.
但是,在较低级别const,给定足够聪明的编译器,应用于参数值的修饰符可以具有一些优化益处.考虑具有相同参数集的两个函数(为简单起见)
int foo(const int a, const double b, const long c) {
/* whatever */
}
void bar(const int a, const double b, const long c) {
/* whatever */
}
Run Code Online (Sandbox Code Playgroud)
让我们说代码中的某处,它们被称为如下
foo(x, d, m);
bar(x, d, m);
Run Code Online (Sandbox Code Playgroud)
通常,编译器在调用函数之前使用参数准备堆栈帧.在这种情况下,堆栈通常会准备两次:每次调用一次.但是聪明的编译器可能会意识到,由于这些函数不会更改其本地参数值(声明为const),因此为第一次调用准备的参数集可以安全地重用于第二次调用.因此,它只能准备一次堆栈.
这是一种相当罕见且模糊的优化,只有在调用时已知函数定义(相同的转换单元或高级全局优化编译器)时才能工作,但有时可能值得一提.
说它"毫无价值"或"没有效果"是不正确的,尽管使用典型的编译器可能就是这种情况.
值得一提的另一个考虑因素是性质不同.那里有编码标准,要求编码人员不要改变初始参数值,如"不要将参数用作普通局部变量,参数值应在整个函数中保持不变".这有点意义,因为有时它可以更容易地确定函数最初给出的参数值(在调试器中,在函数体内).为了帮助实施此编码标准,人们可能会const在参数值上使用说明符.值得与否是一个不同的问题......
| 归档时间: |
|
| 查看次数: |
11607 次 |
| 最近记录: |