你用const能做到什么程度?你只是在必要的时候才把函数变成const,还是从头到尾到处都用它?例如,想象一个简单的变异子,它接受一个布尔参数:

void SetValue(const bool b) { my_val_ = b; }

这个const真的有用吗?就我个人而言,我选择广泛地使用它,包括参数,但在这种情况下,我想知道它是否值得?

我还惊讶地发现,你可以在函数声明中的形参中省略const,但可以在函数定义中包含它,例如:

. h文件

void func(int n, long l);

. cpp文件

void func(const int n, const long l)

这有什么原因吗?这对我来说有点不寻常。


当前回答

1. 根据我的评估,最佳答案是:

根据我的评估,@Adisak的答案是最好的答案。请注意,这个答案在某种程度上是最好的,因为除了使用合理和深思熟虑的逻辑之外,它还使用了最完善的真实代码示例。

2. 我自己的话(同意最好的答案):

For pass-by-value there is no benefit to adding const. All it does is: limit the implementer to have to make a copy every time they want to change an input param in the source code (which change would have no side effects anyway since what's passed in is already a copy since it's pass-by-value). And frequently, changing an input param which is passed by value is used to implement the function, so adding const everywhere can hinder this. and adding const unnecessarily clutters the code with consts everywhere, drawing attention away from the consts that are truly necessary to have safe code. When dealing with pointers or references, however, const is critically important when needed, and must be used, as it prevents undesired side effects with persistent changes outside the function, and therefore every single pointer or reference must use const when the param is an input only, not an output. Using const only on parameters passed by reference or pointer has the additional benefit of making it really obvious which parameters are pointers or references. It's one more thing to stick out and say "Watch out! Any param with const next to it is a reference or pointer!". What I've described above has frequently been the consensus achieved in professional software organizations I have worked in, and has been considered best practice. Sometimes even, the rule has been strict: "don't ever use const on parameters which are passed by value, but always use it on parameters passed by reference or pointer if they are inputs only."

3.谷歌的话(同意我和最好的答案):

(摘自“谷歌c++风格指南”)

对于通过value传递的函数形参,const对调用者没有影响,因此不建议在函数声明中使用。参见tow #109。

对局部变量使用const既不鼓励也不鼓励。

来源:谷歌c++风格指南的“const的使用”部分:https://google.github.io/styleguide/cppguide.html#Use_of_const。这是一个非常有价值的部分,所以请阅读整个部分。

请注意,“tow# 109”代表“本周小贴士#109:函数声明中有意义的const”,这也是一个有用的阅读。它提供了更多的信息,对要做的事情的规定性更少,并且在谷歌c++样式指南关于上面引用的const规则之前出现,但由于它提供的清晰性,上面引用的const规则被添加到谷歌c++样式指南中。

Also note that even though I'm quoting the Google C++ Style Guide here in defense of my position, it does NOT mean I always follow the guide or always recommend following the guide. Some of the things they recommend are just plain weird, such as their kDaysInAWeek-style naming convention for "Constant Names". However, it is still nonetheless useful and relevant to point out when one of the world's most successful and influential technical and software companies uses the same justification as I and others like @Adisak do to back up our viewpoints on this matter.

4. Clang的linter, Clang -tidy,有一些选项:

答:同样值得注意的是,Clang的linter, Clang -tidy,有一个选项,可读性-avoid-const-params-in-decls,描述在这里,以支持在代码库中强制不使用const的值传递函数参数:

检查函数声明的形参是否为顶级const。

声明中的Const值不会影响函数的签名,因此它们不应该放在那里。

例子:

Void f(const字符串);//错误:const是顶级的。 Void f(const string&);//好:const不是顶级的。

为了完整和清晰,我自己再举两个例子:

void f(char * const c_string);   // Bad: const is top level. [This makes the _pointer itself_, NOT what it points to, const]
void f(const char * c_string);   // Good: const is not top level. [This makes what is being _pointed to_ const]

B.它还有这个选项:readable -const-return-type - https://clang.llvm.org/extra/clang-tidy/checks/readability-const-return-type.html

5. 我的务实的方法是如何在这个问题上给出一个风格指南:

我只需复制粘贴到我的风格指南中:

[复制/ START纸浆]

Always use const on function parameters passed by reference or pointer when their contents (what they point to) are intended NOT to be changed. This way, it becomes obvious when a variable passed by reference or pointer IS expected to be changed, because it will lack const. In this use case const prevents accidental side effects outside the function. It is not recommended to use const on function parameters passed by value, because const has no effect on the caller: even if the variable is changed in the function there will be no side effects outside the function. See the following resources for additional justification and insight: "Google C++ Style Guide" "Use of const" section "Tip of the Week #109: Meaningful const in Function Declarations" Adisak's Stack Overflow answer on "Use of 'const' for function parameters" "Never use top-level const [ie: const on parameters passed by value] on function parameters in declarations that are not definitions (and be careful not to copy/paste a meaningless const). It is meaningless and ignored by the compiler, it is visual noise, and it could mislead readers" (https://abseil.io/tips/109, emphasis added). The only const qualifiers that have an effect on compilation are those placed in the function definition, NOT those in a forward declaration of the function, such as in a function (method) declaration in a header file. Never use top-level const [ie: const on variables passed by value] on values returned by a function. Using const on pointers or references returned by a function is up to the implementer, as it is sometimes useful. TODO: enforce some of the above with the following clang-tidy options: https://clang.llvm.org/extra/clang-tidy/checks/readability-avoid-const-params-in-decls.html https://clang.llvm.org/extra/clang-tidy/checks/readability-const-return-type.html

下面是一些演示上述const规则的代码示例:

参数示例: (有些是从这里借来的)

void f(const std::string);   // Bad: const is top level.
void f(const std::string&);  // Good: const is not top level.

void f(char * const c_string);   // Bad: const is top level. [This makes the _pointer itself_, NOT what it points to, const]
void f(const char * c_string);   // Good: const is not top level. [This makes what is being _pointed to_ const]

示例: (有些是从这里借来的)

// BAD--do not do this:
const int foo();
const Clazz foo();
Clazz *const foo();

// OK--up to the implementer:
const int* foo();
const int& foo();
const Clazz* foo();

复制/ PASTE黑的外星人探索铝

关键词:const在函数形参中的应用;编码标准;C和c++编码标准;编码规则;最佳实践;代码标准;Const返回值

其他回答

确实没有理由将值形参设为“const”,因为函数只能修改变量的副本。

使用“const”的原因是如果你通过引用传递更大的东西(例如有很多成员的结构体),在这种情况下,它确保函数不能修改它;或者更确切地说,如果您试图以常规方式修改它,编译器将报错。它可以防止它被意外修改。

我不会把const放在形参上——每个人都知道布尔值(而不是布尔&)是常量,所以添加它会让人们认为“等等,什么?”或者甚至认为你是通过引用传递形参的。

在关于comp.lang.c++的旧的“每周大师”文章中有关于这个主题的很好的讨论。主持。

相应的GOTW文章可以在Herb Sutter的网站上找到。

有时候(太频繁了!)我必须理清别人的c++代码。我们都知道别人的c++代码几乎从定义上看是一团乱子:)所以我要破译本地数据流的第一件事就是在每个变量定义中放入const,直到编译器开始吠叫。这也意味着const限定值参数,因为它们只是由调用者初始化的花哨局部变量。

啊,我希望变量默认是const的,而非const的变量是可变的:)

关于编译器优化:http://www.gotw.ca/gotw/081.htm