C++ 值参数的常量正确性
我知道关于const的正确性几乎没有什么问题,其中指出函数的声明及其定义不需要与值参数一致。这是因为值参数的常量只在函数内部起作用。这很好:C++ 值参数的常量正确性,c++,pass-by-value,const-correctness,C++,Pass By Value,Const Correctness,我知道关于const的正确性几乎没有什么问题,其中指出函数的声明及其定义不需要与值参数一致。这是因为值参数的常量只在函数内部起作用。这很好: // header int func(int i); // cpp int func(const int i) { return i; } 这样做真的是最佳实践吗?因为我从来没见过有人这么做。我在其他地方看过这段引文(不确定来源),这段引文已经讨论过: 事实上,对于编译器来说,无论是否在值参数前面包含此常量,函数签名都是相同的 “避免在函数声明
// header
int func(int i);
// cpp
int func(const int i) {
return i;
}
这样做真的是最佳实践吗?因为我从来没见过有人这么做。我在其他地方看过这段引文(不确定来源),这段引文已经讨论过:
事实上,对于编译器来说,无论是否在值参数前面包含此常量,函数签名都是相同的
“避免在函数声明中使用常量传递值参数。如果不修改参数,则仍在同一函数的定义中使用常量。”
第二段说不要在声明中加入常量。我假设这是因为值参数的常量作为接口定义的一部分是没有意义的。这是一个实现细节
基于此建议,是否也建议使用指针参数的指针值?(这对引用参数没有意义,因为无法重新指定引用。)
摘要:生成值参数有助于捕获某些逻辑错误。这是最佳实践吗?您是否将const排除在头文件之外?常量指针值是否同样有用?为什么
一些参考资料:
常数值参数有用时的示例:
bool are_ints_equal(const int i, const int j) {
if (i = j) { // without the consts this would compile without error
return true;
} else {
return false;
}
// return i = j; // I know it can be shortened
}
我已经读过很多次,在函数const中生成值参数是一件不好的事情,因为这是不必要的 然而,我发现它偶尔对我有帮助,可以检查我的实现是否做了我不想做的事情(如问题末尾的示例所示) 因此,虽然它可能不会为调用者增加价值,但它有时确实会为我作为实现者增加一点点价值,而且它不会从调用者身上带走任何东西。所以我认为使用它没有坏处 例如,我可能正在实现一个C函数,该函数使用两个指向缓冲区的指针—一个指向开始的指针,一个指向结束的指针。我将把数据放在缓冲区中,但要确保不会溢出结尾。因此,在函数内部有一段代码,在我向它添加数据时,它会增加指针。将指向缓冲区结尾的指针设为
const
参数将确保我不会编写错误代码,该错误会意外地增加结尾边界指针,而不是我真正应该增加的指针
一个具有如下特征码的fillArray函数:
size_t fillArray( data_t* pStart, data_t* const pEnd);
void foo(const int count /* … */)
{
int temp = count; // can't modify count, so we need a copy of it
++temp;
/* … */
}
当我真的想增加pStart
时,将防止我意外地增加pEnd
。这并不是什么大问题,但我很确定每个在C语言中编程过一段时间的人都遇到过这样的错误。我的看法:
这不是一个坏主意,但问题很小,你的精力最好花在其他事情上
在您的问题中,您提供了一个很好的示例,说明它何时可能捕捉到错误,但有时您也会这样做:
size_t fillArray( data_t* pStart, data_t* const pEnd);
void foo(const int count /* … */)
{
int temp = count; // can't modify count, so we need a copy of it
++temp;
/* … */
}
无论哪种方法,优点和缺点都是次要的。不幸的是,一些编译器(我正在看你,Sun CC!)错误地区分声明为常量的参数和未声明为常量的参数,并且可能会在未定义的函数中出错。我喜欢这种情况下的常量正确性:
void foo(const Bar&b)//我知道b不能更改
{
//用b做点什么
}
这让我可以使用
b
而不用担心修改它,但我不必支付复制构造函数的费用。我认为这取决于你的个人风格
它不会增加或减少客户端可以传递给函数的内容。本质上,它就像一个编译时断言。如果这有助于你知道价值不会改变,那就去做吧,但我不认为其他人有什么理由这么做
我可能不这么做的一个原因是value参数的常量是一个实现细节,您的客户不需要知道。如果您后来(有意)更改了函数,使其确实更改了该值,则需要更改函数的签名,这将迫使客户端重新编译
这类似于为什么有些人建议不要使用公共虚拟方法(函数virtualness是一个应该对客户机隐藏的实现细节),但我不在这一特定阵营中。如果存在const关键字;这意味着“i”(常量类型)的值不能修改。 如果在foo函数中更改了“i”的值,编译器将抛出错误: 无法修改常量对象 但更改'*i'(即*i=3;)意味着您并没有更改'i'的值,而是更改由'i'指向的地址的值
实际上,const函数适用于不应被函数更改的大型对象。+1表示这不是一个坏主意,并指出问题很小。但在您复制内部参数之前,我只需删除const(除非您复制“count”)“始终,作为不对参数进行操作的原则,并且不仅仅是因为常量阻止了您)通常,当您像这样修改变量时,您正在更改语义含义。例如:void foo(const int index0based){const int index1based=index0based+1;}您可以将其称为index并对其进行更改,但对于5年后出现的糟糕的维护程序员来说,这一点要清楚得多。维护程序员的问题是我最关心的;)事实上,我见过与您的示例类似的代码。如果传入项,则计数,而不是进行本地
int currentCount=count代码>,在函数运行时使用并调整参数