Sco*_*ith 14 c++ const const-correctness
我最近与另一位C++开发人员就以下用途进行了交流const:
void Foo(const int bar);
Run Code Online (Sandbox Code Playgroud)
他认为const以这种方式使用是很好的做法.
我认为它对函数的调用者没有任何作用(因为参数的副本将被传递,因此对于覆盖没有额外的安全保证).此外,这样做可以防止实现者Foo修改其参数的私有副本.因此,它既要求又要宣传实施细节.
不是世界末日,但肯定不是值得推荐的良好做法.
我很好奇别人对这个问题的看法.
好吧,我没有意识到参数的常数没有考虑到函数的签名.因此,可以const在实现(.cpp)中标记参数,而不是在标题(.h)中标记- 并且编译器就可以了.既然如此,我想政策应该与制作局部变量const相同.
人们可以提出这样的论点:在标题和源文件中具有不同的看起来签名会使其他人感到困惑(因为它会使我感到困惑).虽然我试着用我写的任何内容来遵循最小惊讶原则,但我认为期望开发人员认为这是合法且有用的是合理的.
pae*_*bal 27
if(NULL == p)模式吗?有很多人会说"你必须写这样的代码":
if(NULL == myPointer) { /* etc. */ }
Run Code Online (Sandbox Code Playgroud)
代替
if(myPointer == NULL) { /* etc. */ }
Run Code Online (Sandbox Code Playgroud)
基本原理是第一个版本将保护编码器免于代码拼写错误,例如将"=="替换为"="(因为禁止将值赋给常量值).
以下可以被视为这种有限if(NULL == p)模式的扩展:
无论类型如何,"const"都是一个限定符,我向编译器说" 我不希望值发生变化,所以如果我说谎,请发送编译器错误消息 ".
例如,这种代码将显示编译器何时可以帮助我:
void bar_const(const int & param) ;
void bar_non_const(int & param) ;
void foo(const int param)
{
const int value = getValue() ;
if(param == 25) { /* Etc. */ } // Ok
if(value == 25) { /* Etc. */ } // Ok
if(param = 25) { /* Etc. */ } // COMPILE ERROR
if(value = 25) { /* Etc. */ } // COMPILE ERROR
bar_const(param) ; // Ok
bar_const(value) ; // Ok
bar_non_const(param) ; // COMPILE ERROR
bar_non_const(value) ; // COMPILE ERROR
// Here, I expect to continue to use "param" and "value" with
// their original values, so having some random code or error
// change it would be a runtime error...
}
Run Code Online (Sandbox Code Playgroud)
在那些情况下,可能由代码错误或函数调用中的一些错误发生,将由编译器捕获,这是一件好事.
碰巧:
void foo(const int param) ;
Run Code Online (Sandbox Code Playgroud)
和:
void foo(int param) ;
Run Code Online (Sandbox Code Playgroud)
有相同的签名.
这是一件好事,因为,如果函数实现者决定一个参数在函数内被认为是const,那么用户不应该,也不需要知道它.
这解释了为什么我的函数声明给用户省略了const:
void bar(int param, const char * p) ;
Run Code Online (Sandbox Code Playgroud)
保持声明尽可能清晰,而我的函数定义尽可能地添加它:
void bar(const int param, const char * const p)
{
// etc.
}
Run Code Online (Sandbox Code Playgroud)
使我的代码尽可能健壮.
不过,我被我的模式所困扰.
在一些将保持匿名的破坏的编译器(其名称以" Sol " 开头并以" aris CC " 结尾),上面的两个签名可以被视为不同(取决于上下文),因此,运行时链接可能会失败.
由于项目也是在Unix平台上编译的(Linux和Solaris),在这些平台上,未定义的符号在执行时被解析,这在执行过程中引发了运行时错误.
所以,因为我不得不支持所说的编译器,所以我结束了使用已经开始的原型来污染我的标题.
但我仍然认为这种在函数定义中添加const的模式是一个很好的模式.
注意:Sun Microsystems甚至还用球来隐藏他们破碎的破损,并且" 无论如何都是邪恶的模式,所以你不应该使用它 "的声明.见http://docs.oracle.com/cd/E19059-01/stud.9/817-6698/Ch1.Intro.html#71468
必须注意的是,Bjarne Stroustrup似乎反对考虑void foo(int)相同的原型void foo(const int):
不过,并非所有接受的功能都是我认为的改进.例如,void f(T)和void f(const T)的规则表示相同的函数(由于Pl兼容性原因由Tom Plum提出)[有]被投票到C++中的可疑区别"在我的尸体上".
来源:Bjarne的Stroustrup的
演进语言在和现实世界中:C++ 1991-2006,5,语言特点:1991- 1998年,P21.
http://www.stroustrup.com/hopl-almost-final.pdf
考虑到Herb Sutter提供了相反的观点,这很有趣:
准则:避免在函数声明中使用const pass-by-value参数.如果不修改参数const仍然在同一函数的定义中.
来源:Herb Sutter
Exceptional C++,Item 43:Const- Correctness,p177-178.
这已经多次讨论过,大多数人最终不得不同意不同意.就个人而言,我同意这是毫无意义的,并且标准隐含地同意 - 顶级const(或volatile)限定符不构成函数签名的一部分.在我看来,想要使用这样的顶级限定符表明(强烈地)该人可能会为将界面与实现分离而口头上说,但并不真正理解这种区别.
另一个小细节:虽然它确实适用于引用以及指针...
| 归档时间: |
|
| 查看次数: |
1508 次 |
| 最近记录: |