2009-11-12 71 views
24

我知道关于const正确性的问题很少,它声明函数的声明及其定义不需要同意值参数。这是因为值参数的常量只在函数内部很重要。这很好:Const参数值的正确性

// header 
int func(int i); 

// cpp 
int func(const int i) { 
    return i; 
} 

这样做真的是最佳做法吗?因为我从来没有见过任何人这样做。我已经看到了这个报价(不知道来源的)在其他地方这个已经讨论:

"In fact, to the compiler, the function signature is the same whether you include this const in front of a value parameter or not."

"Avoid const pass-by-value parameters in function declarations. Still make the parameter const in the same function's definition if it won't be modified."

第二段说,不要把常量的声明。我认为这是因为作为接口定义的一部分,值参数的常量是没有意义的。这是一个实现细节。

根据这个建议,是否也推荐指针参数的指针值? (因为你不能重新分配的参考这是在参考参数毫无意义。)

// header 
int func1(int* i); 
int func2(int* i); 

// cpp 
int func1(int* i) { 
    int x = 0; 

    *i = 3; // compiles without error 
    i = &x; // compiles without error 

    return *i; 
} 
int func2(int* const i) { 
    int x = 0; 

    *i = 3; // compiles without error 
    i = &x; // compile error 

    return *i; 
} 

总结:制作值参数是捕捉一些逻辑错误。这是最佳做法吗?你是否把const放在头文件的极端?它对const指针值有用吗?为什么或者为什么不?

一些参考:

C++ const keyword - use liberally? Use of 'const' for function parameters

当常数值参数都是有用的例子:

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 
} 
+0

它惹人“如果(i = j)的”错误在这种情况下,但没有捕捉到所有这些错误,所以我不会为这个特定的基本原理感到兴奋(因为你可以用变量来做同样的错误)。即使没有const,如果你告诉它你想要警告,你的编译器也会警告你。 – nobar 2009-11-13 04:29:52

+0

'if(i = j)'让人兴奋的一点是要认识到常量值参数不仅仅是绒毛。迈克尔伯尔的例子甚至比这个更好。 – jmucchiello 2009-11-13 06:35:14

+2

在不更改函数参数的情况下,应该对它们进行约束,因为A)它更安全,B)它是自记录的,C)它更易于调试。另外,原型和头文件应该标记为const。如果只是在函数头部完成,那很令人困惑。有关在函数中创建临时变量的争论是一种情况,您可能不需要声明参数const。这是我的2便士。 – 2011-09-19 20:52:23

回答

7

我对此采取:

这不是一个坏主意,但问题是次要的,你的能量可能会在其他的事情可能会更好一些。

在你的问题,你所提供的,当它可能赶上一个错误一个很好的例子,但偶尔也最终会做这样的事情:

void foo(const int count ...) 
{ 
    int temp = count; // can't modify count, so we need a copy of it 
    ++temp; 

    /* ... */ 
} 

的利弊是次要的两种方式。

+3

+1表示这不是一个坏主意,并指出这个问题很小。但在你复制参数之前,我只需要移除const(除非你总是复制“count”,作为不对参数进行操作的原则,而不仅仅是因为const阻止你) – 2009-11-12 18:27:39

+8

通常当你像这样修改变量,你正在改变语义。例如:void foo(const int index0based){const int index1based = index0based + 1;}您可以将其称为索引并对其进行更改,但对于5年后出现的维护程序员而言,这一点更为明确。 – Bill 2009-11-12 18:48:11

+0

@票据,优点! – 2009-11-12 18:51:48

9

我在一个函数读取很多次,创造价值的参数const是一件坏事,因为它是不必要的。

但是,我发现它偶尔对我有帮助,作为一个检查,我的实现不会做我不打算的事情(就像你的问题结尾的例子)。

所以,虽然它可能不会增加调用者的价值,但它有时会为我实施者增加一点价值,并且它不会带走任何东西。所以我认为没有害处使用它。

例如,我可能正在实现一个C函数,它将一对指针指向一个缓冲区 - 一个指向开始的指针和一个指向结尾的指针。我将把数据放入缓冲区,但要确保不会超出最后。所以在函数里面有一些代码会在我添加数据时增加一个指针。使指针指向缓冲区末尾的const参数将确保我不编码意外增加结束边界指针的错误,而不是我真的应该增加的指针。

所以有这样的签名fillArray功能:

size_t fillArray(data_t* pStart, data_t* const pEnd); 

会阻止我意外增加pEnd当我真正的意思是递增pStart。这不是一件大事,但我很确定每个在C中编程了一段时间的人都遇到过这样的错误。

+0

非常好。我正在寻找一个const指针值的好例子。 – jmucchiello 2009-11-12 19:02:34

1

不幸的是,一些编译器(我看着你,太阳CC!)声明不正确的参数常量和那些没有宣布这样区分,你可以得到有关未定义函数的错误。

-2

我喜欢的情况const正确性是这样的:
void foo(const Bar &b) //I know b cannot be changed
{
//do something with b
}

这让我使用b而不必担心修改它,但我没有付出拷贝构造函数的成本。

+8

我们不是在谈论参考参数。仅限数值参数。 – jmucchiello 2009-11-12 19:00:58

0

我认为这取决于你的个人风格。

它不增加或减少客户端可以传递给你的函数。本质上它就像一个编译时断言。如果它帮助你知道价值不会改变,那就去做吧,但我认为别人没有这么做的重要原因。

一个原因,我可能不会做它该值参数的常量性是一个实现细节,你的客户端不需要了解。如果您以后(故意)更改函数以确实更改该值,则需要更改函数的签名,这将强制客户重新编译。

这类似于为什么有些人建议有没有公共虚拟方法(功能虚拟岬是一个实现细节应该从客户端被隐藏),但我不是在特定的阵营。

+2

重读这个问题。头文件没有const,因为正如你所说,调用者并不关心实现是否修改局部变量。这是一个严格的问题,在实施方面是否值得。 – jmucchiello 2009-11-12 19:06:43

0

如果存在const关键字;它意味着'我'(这是const类型)的值不能被修改。 如果“i”的值foo的函数编译器内改变将引发错误:“

Can not modify const object

但改变‘* I’(即* I = 3;)意味着你不能改变的值‘我’,但由“我”

其实指向的地址的值,const的功能适用于不应该由功能改变大对象。

0

我们都必须解开别人的C++代码时有发生。而这别人的C++代码是一个完全混乱的定义:D。

因此,我经常要做的第一件事情就是解密它(本地&全局数据流),将const放在每个变量定义中,直到编译器发出抱怨。这也意味着const限定值的参数,它确实有助于避免在函数中间被修改的变量,而我没有注意到它...

所以,我真的很感激,当别人有常量到处(包括值参数):d