Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 值参数的常量正确性_C++_Pass By Value_Const Correctness - Fatal编程技术网

C++ 值参数的常量正确性

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; } 这样做真的是最佳实践吗?因为我从来没见过有人这么做。我在其他地方看过这段引文(不确定来源),这段引文已经讨论过: 事实上,对于编译器来说,无论是否在值参数前面包含此常量,函数签名都是相同的 “避免在函数声明

我知道关于const的正确性几乎没有什么问题,其中指出函数的声明及其定义不需要与值参数一致。这是因为值参数的常量只在函数内部起作用。这很好:

// 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,在函数运行时使用并调整参数