是“const”;按值传递时函数参数中必需的吗?
在以下 C++ 函数中:
void MyFunction(int age, House &purchased_house)
{
// ...
}
void MyFunction(const int age, House &purchased_house)
{
// ...
}
在这两个函数中,age
都是按值传递的。我想知道 const 关键字是否必要:对我来说这似乎是多余的,但也很有帮助(作为额外的指示,变量不会改变)。
有人对上述哪一个(如果有的话)更好有什么意见吗?
In the following C++ functions:
void MyFunction(int age, House &purchased_house)
{
// ...
}
void MyFunction(const int age, House &purchased_house)
{
// ...
}
In both, age
is passed by value. I am wondering if the const
keyword is necessary: It seems redundant to me, but also helpful (as an extra indication the variable will not be changing).
Does anyone have any opinion as to which (if any) of the above are better?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
首先,它只是一个实现细节,如果您将const放在那里,不要将其放在声明集(标头)中。仅将其放在实现文件中:
定义中参数是否为 const 纯粹是实现细节,不应该成为接口的一部分。
这种事我不常见,我也不会这么做。拥有参数 const 会让我更困惑而不是帮助,因为我会立即将其模式匹配失败为“const int &age”:) 当然,这与使用 const 完全不同另一个层面:
在这种情况下,const 将影响函数是否可以更改调用者的参数。这个意义上的const应该尽可能多地使用,因为它可以帮助确保程序的正确性并改进代码的自记录。
First, it's just an implementation detail, and if you put const there, don't put it in the declaration set (header). Only put it in the implementation file:
Whether or not a parameter is const in a definition is purely an implementation detail, and should not be part of the interface.
I've not seen this sort of thing often, and i also don't do this. Having the parameter const would confuse me more often than help, because i would immediately pattern-match-fail it to "const int &age" :) The matter of course is entirely different from having const at another level:
In this case, the const will affect whether the function can change the caller's argument. Const in this meaning should be used as often as possible, because it can help ensuring program correctness and improve self-documenting the code.
我建议阅读赫伯·萨特。卓越的 C++。其中有一章“常量正确性”。
这意味着这个签名
实际上与以下相同:
因此,对于编译器来说,声明函数的方式没有区别。并且您不能通过将 const 关键字放在按值传递参数前面来重载它。
进一步阅读 Herb Sutter 的建议:
他建议避免这种情况:
因为该 const 令人困惑、冗长且多余。
但在定义中,您应该这样做(如果您不更改参数):
因此,您将确保即使在函数体 1000 行之后,您始终保持数字不变。编译器将禁止您将数字作为非常量引用传递给另一个函数。
I recommend reading Herb Sutter. Exceptional C++. There is a chapter "Const-Correctness".
It means that this signature
is effectively the same as this:
So, to the compiler there is no difference how you declare a function. And you can't overload it by putting the const keyword in front of a pass by value parameter.
Read further, what Herb Sutter recommends:
He recommends to avoid this:
Because that const is confusing, verbose and redundant.
But in the definition, you should do that (if you won't change the parameter):
So, you'll be sure that even after 1000 lines of function's body you always have the number untouched. The compiler will prohibit you from passing the number as a non-const reference to another function.
恕我直言,这是过度使用。
当您说“const int Age,...”时,您实际上说的是“您甚至无法更改函数内的本地副本”。您所做的实际上是在程序员想要更改年龄/通过非常量引用传递它时,通过强制他使用另一个本地副本来降低程序员代码的可读性。
任何程序员都应该熟悉按引用传递和按值传递之间的区别,就像任何程序员都应该理解“const”一样。
This, IMHO, is overusing.
When you say 'const int age,...' what you actually say is "you can't change even the local copy inside your function". What you do is actually make the programmer code less readable by forcing him to use another local copy when he wants to change age/pass it by non-const reference.
Any programmer should be familiar with the difference between pass by reference and pass by value just as any programmer should understand 'const'.
你不仅表明它不会改变,它还会阻止你的代码认为它可以改变,并且它会在编译时被捕获。
You not only indicate that it will not change, it will prevent your code from thinking it can and it will be caught at compilation time.
请参阅 Meyers 和“Effective C++”,并充分使用 const,尤其是在引用传递语义方面。
在原子变量的情况下,效率并不重要,但代码清晰度仍然有好处。
See Meyers and 'Effective C++' on this, and do use const liberally, especially with pass-by-reference semantics.
In this case of atomic variables, efficiency does not matter but code clarity still benefits.
嗯,正如其他人已经说过的,从C++语言的角度来看,上面的const对函数签名没有影响,即无论是否const<,函数类型都保持不变/code> 是否存在。它在抽象 C++ 语言级别上的唯一影响是您无法在函数体内修改此参数。
然而,在较低级别,如果编译器足够聪明,应用于参数值的 const 修饰符可以带来一些优化优势。考虑两个具有相同参数集的函数(为了简单起见)
假设在代码中的某处调用它们,如下所示
通常,编译器在调用函数之前准备带有参数的堆栈帧。在这种情况下,堆栈通常会准备两次:每次调用一次。但聪明的编译器可能会意识到,由于这些函数不会更改其本地参数值(用 const 声明),因此为第一次调用准备的参数集可以安全地重用于第二次调用。因此它只能准备一次堆栈。
这是一种相当罕见且晦涩的优化,只有在调用时已知函数的定义(相同的翻译单元或高级的全局优化编译器)时才能起作用,但有时可能值得一提。
说它“毫无价值”或“没有效果”是不正确的,即使对于典型的编译器来说可能是这种情况。
另一个值得一提的考虑因素具有不同的性质。有一些编码标准,要求编码人员不要更改初始参数值,例如“不要将参数用作普通局部变量,参数值应在整个函数中保持不变”。这是有道理的,因为有时它可以更容易地确定函数最初给出的参数值(在调试器中,在函数体内)。为了帮助执行此编码标准,人们可能会在参数值上使用 const 说明符。值不值钱是另外一个问题了...
Well, as other have already said, from the point of view of C++ language, the above
const
has no effect on function signature, i.e. the function type remains the same regardless of whether theconst
is there or not. The only effect it has at the level of abstract C++ language is that you can't modify this parameter inside the function body.However, at the lower level, the
const
modifier applied to the parameter value can have some optimization benefits, given a sufficiently clever compiler. Consider two functions with the same parameter set (for simplicity)Let's say somewhere in the code they are called as follows
Normally, compilers prepare stack frame with arguments before they call a function. In this case the stack will usually be prepared twice: once for each call. But a clever compiler might realize that since these functions do not change their local parameter values (declared with
const
), the argument set prepared for the first call can be safely reused for the second call. Thus it can prepare the stack only once.This is a rather rare and obscure optimization, which can only work when the definition of the function is known at the point of the call (either same translation unit, or an advanced globally-optimizing compiler), but sometimes it might be worth mentioning.
It is not correct to say that it is "worthless" or "has no effect", even though with a typical compiler this might be the case.
Another consideration that is worth mentioning is of different nature. There are coding standards out there, which require coders not to change the initial parameter values, as in "don't use parameters as ordinary local variables, parameter values should remain unchanged throughout the function". This kinda makes sense, since sometimes it makes it easier to determine what parameter values the function was originally given (while in debugger, inside the body of the function). To help enforce this coding standard, people might use
const
specifiers on parameter values. Whether it is worth it or not is a different question...使用
const
的好处之一是,您不会意外更改MyFunction
中间的age
值(如果您忘记了它不是通过引用传递)。一个“缺点”是您无法使用foo.process(++age);
等代码回收age
。One benefit of using
const
is that you cannot accidentally change the value ofage
in the middle ofMyFunction
(in the event you forgot it was not pass by reference). One "disadvantage" is that you can't recycleage
with code likefoo.process(++age);
.你是对的,“const int Age”的唯一目的是年龄不能改变。然而,这对于大多数程序员来说可能非常令人困惑。因此,如果这些方法没有在您的代码中广泛使用,我建议省略 const。
You're correct, the only purpose of "const int age" is that age can not be changed. This can be however very confusing for most of programmers. So if these approach is not used widely in your code, I'd advice to omit const.
第二种变体更好。在第一个中,您可能会意外更改变量年龄。
Second variant is better. In the first one you can accidently change variable age.
如果(且仅当)您将在任何其他不会被修改的局部变量上使用它,您应该在参数上使用 const:
有时在可能的情况下将局部变量标记为 const 很方便,因为这意味着您可以查看声明并知道这就是值,而无需考虑中间代码。您将来可以轻松地更改它(并确保您没有破坏函数中的代码,如果变量现在表示的内容略有不同,则可以更改变量的名称,这是可以更改的,而不是以前的不可更改的事物)。
与此相反,它确实使代码更加冗长,并且在简短的函数中,哪些变量发生变化而哪些变量没有变化几乎总是非常明显。
所以,要么:
要么:
You should use
const
on a parameter if (and only if) you would use it on any other local variable that won't be modified:It's sometimes handy to mark local variables const where possible, since it means you can look at the declaration and know that's the value, without thinking about intermediate code. You can easily change it in future (and make sure you haven't broken the code in the function, and maybe change the name of the variable if it now represents something slightly different, which is changeable, as opposed to the previous non-changing thing).
As against that, it does make the code more verbose, and in a short function it's almost always very obvious which variables change and which don't.
So, either:
or:
以下是我发现的一些很棒的文章和一本书,解释了使用 const 的优点:
C++ const 正确性
C++ 专家的建议:保持常量正确
来自 Scott Meyers 的有效 C++
我可以向您提出以下格言吗?
如果一个对象/变量可以被限定为常量,那么它应该是。最坏的情况下,它不会花费任何费用。充其量,您将记录代码中对象/变量的作用,这将使编译器有机会进一步优化您的代码。
一些编译器忽略了使用“const”来挖掘优化的潜力,这导致许多专家在可以使用常量参数按值时忽略了它。这种做法需要更加严格,但不会有害。在最坏的情况下,你不会失去任何东西,但你也不会获得任何东西,在最好的情况下,你会从使用这种方法中获益。
对于那些似乎不了解函数/方法的按值参数中 const 的实用程序的人...这里有一个简短的示例,解释了原因:
.cpp
如果我删除前面的 const 会发生什么int MAX 和我在里面写了 MAX + 1 这样吗?
那么你的程序就会崩溃!现在,为什么有人会写“MAX += MAX;” ?也许是人为错误,也许程序员那天感觉不舒服,或者也许程序员根本不知道如何编写 C/C++ 代码。如果你有 const,代码甚至都不会编译!
安全代码就是好代码,当你拥有它时添加“const”不需要任何成本!
这是来自不同帖子的非常相似问题的答案:
这是链接:答案。
Here are some great articles and a book I found explaining the advantages of using const:
C++ const Correctness
Advice From the C++ Experts: Be Const-Correct
Effective C++ from Scott Meyers
Can I propose the following maxim to you?
If an object/variable can be qualified has being constant, it should be. At worst, it will not cost anything. At best, you will be documenting the role of the object/variable in your code and it will allow the compiler the opportunity to optimize your code even more.
Some compilers neglect to exploit the potential of optimization with the use of 'const' and that has lead many experts to neglect the use of constant parameters by value when it could be used. This practice takes more strictness, but it will not be harmful. At worst, you do not lose anything , but you do not gain anything too and at best, you win from using this approach.
For those who do not seem to understand the utility of a const in a by value parameter of a function/method... here is a short example that explains why:
.cpp
What would had happen if I would had removed the const in front of int MAX and I had written MAX + 1 inside like this?
Well your program would crash! Now, why would someone write "MAX += MAX;" ? Perhaps human error, maybe the programmer was not feeling well that day or perhaps the programmer simply did not know how to write C/C++ code. If you would have had const, the code would have not even compiled!
Safe code is good code and it does not cost anything to add "const" when you have it!
Here is an answer from a different post for a very similar question:
Here is the link: answer.
拥有一个通过值 const 传递的原始类型几乎毫无价值。将 const 传递给函数通常作为与调用者的契约有用,即函数不会更改该值。在这种情况下,因为 int 是按值传递的,所以函数无法进行任何在函数外部可见的更改。
另一方面,如果不对对象进行任何更改,则引用和重要对象类型应始终使用 const。理论上,这可能允许一些优化,但最大的胜利是我上面提到的合同。当然,缺点是它会使您的界面变得更大,并且将 const 改造为现有系统(或使用不在各处使用 const 的第 3 方 API)是一件困难的事情。
Having a primitive type that is passed by value const is pretty much worthless. Passing a const to a function is generally useful as a contract with the caller that the funciton will not change the value. In this case, because the int is passed by value, the function can't make any changes that will be visible outside the function.
On the other hand, rreferences and non trivial object types should always use const if there is not going to be any changes made to the object. In theory this might allow for some optimization, but the big win is the contract I mentioned above. The downside is of course, that it can make your interface much larger, and const it a tough thing to retrofit into an existing system (or with a 3rd party API not using const everywhere).