C++ 使用“const”作为函数参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/117293/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Use of 'const' for function parameters
提问by Rob
How far do you go with const
? Do you just make functions const
when necessary or do you go the whole hog and use it everywhere? For example, imagine a simple mutator that takes a single boolean parameter:
你走多远const
?你只是const
在必要时创建函数还是全力以赴并在任何地方使用它?例如,想象一个简单的 mutator,它接受一个布尔参数:
void SetValue(const bool b) { my_val_ = b; }
Is that const
actually useful? Personally I opt to use it extensively, including parameters, but in this case I wonder if it's worthwhile?
这const
真的有用吗?我个人选择广泛使用它,包括参数,但在这种情况下,我想知道它是否值得?
I was also surprised to learn that you can omit const
from parameters in a function declaration but can include it in the function definition, e.g.:
我还惊讶地发现您可以const
在函数声明中省略参数,但可以将其包含在函数定义中,例如:
.h file
.h 文件
void func(int n, long l);
.cpp file
.cpp 文件
void func(const int n, const long l)
Is there a reason for this? It seems a little unusual to me.
是否有一个原因?对我来说似乎有点不寻常。
采纳答案by Greg Rogers
The reason is that const for the parameter only applies locally within the function, since it is working on a copy of the data. This means the function signature is really the same anyways. It's probably bad style to do this a lot though.
原因是参数的 const 仅在函数内局部应用,因为它正在处理数据的副本。这意味着函数签名无论如何都是一样的。尽管如此,这样做可能是一种糟糕的风格。
I personally tend to not use const except for reference and pointer parameters. For copied objects it doesn't really matter, although it can be safer as it signals intent within the function. It's really a judgement call. I do tend to use const_iterator though when looping on something and I don't intend on modifying it, so I guess to each his own, as long as const correctness for reference types is rigorously maintained.
我个人倾向于不使用 const 除了引用和指针参数。对于复制的对象,这并不重要,尽管它可以更安全,因为它在函数内表示意图。这真的是一个判断电话。我确实倾向于使用 const_iterator 虽然在循环某些东西时我不打算修改它,所以我猜每个人都是他自己的,只要严格维护引用类型的 const 正确性。
回答by rlerallut
"const is pointless when the argument is passed by value since you will not be modifying the caller's object."
“当参数按值传递时,const 毫无意义,因为您不会修改调用者的对象。”
Wrong.
错误的。
It's about self-documenting your code and your assumptions.
这是关于自我记录您的代码和您的假设。
If your code has many people working on it and your functions are non-trivial then you should mark "const" any and everything that you can. When writing industrial-strength code, you should always assume that your coworkers are psychopaths trying to get you any way they can (especially since it's often yourself in the future).
如果你的代码有很多人在处理它并且你的函数很重要,那么你应该标记“const”任何你能做的。在编写具有工业强度的代码时,您应该始终假设您的同事是精神病患者,他们试图以任何可能的方式让您着迷(特别是因为将来通常是您自己)。
Besides, as somebody mentioned earlier, it mighthelp the compiler optimize things a bit (though it's a long shot).
此外,正如前面有人提到的,它可能会帮助编译器优化一些东西(尽管这是一个很长的镜头)。
回答by Constantin
Sometimes (too often!) I have to untangle someone else's C++ code. And we all know that someone else'sC++ code is a complete mess almost by definition :) So the first thing I do to decipher local data flow is put constin every variable definition until compiler starts barking. This means const-qualifying value arguments as well, because they are just fancy local variables initialized by caller.
有时(太频繁了!)我必须解开其他人的 C++ 代码。而且我们都知道,根据定义,其他人的C++ 代码几乎是一团糟:) 因此,我为破译本地数据流所做的第一件事就是将const放入每个变量定义中,直到编译器开始吠叫。这也意味着 const 限定的值参数,因为它们只是由调用者初始化的花哨的局部变量。
Ah, I wish variables were constby default and mutablewas required for non-const variables :)
嗯,我希望变量是常量默认和可变被要求对非const变量:)
回答by Ben Straub
The following two lines are functionally equivalent:
以下两行在功能上是等效的:
int foo (int a);
int foo (const int a);
Obviously you won't be able to modify a
in the body of foo
if it's defined the second way, but there's no difference from the outside.
显然a
,foo
如果它是第二种方式定义的,则您将无法在主体中进行修改,但与外部没有区别。
Where const
really comes in handy is with reference or pointer parameters:
凡const
真正派上用场参照或指针参数:
int foo (const BigStruct &a);
int foo (const BigStruct *a);
What this says is that foo can take a large parameter, perhaps a data structure that's gigabytes in size, without copying it. Also, it says to the caller, "Foo won't* change the contents of that parameter." Passing a const reference also allows the compiler to make certain performance decisions.
这意味着 foo 可以接受一个大参数,可能是一个千兆字节大小的数据结构,而无需复制它。此外,它对调用者说,“Foo 不会* 更改该参数的内容。” 传递 const 引用还允许编译器做出某些性能决定。
*: Unless it casts away the const-ness, but that's another post.
*:除非它抛弃了常量性,但那是另一篇文章。
回答by Adisak
Extra Superfluous const are bad from an API stand-point:
从 API 的角度来看,额外的多余常量是不好的:
Putting extra superfluous const's in your code for intrinsic type parameters passed by value clutters your APIwhile making no meaningful promise to the caller or API user (it only hampers the implementation).
在您的代码中为通过值传递的内在类型参数添加额外多余的常量会使您的 API变得混乱,同时对调用者或 API 用户没有任何有意义的承诺(它只会妨碍实现)。
Too many 'const' in an API when not needed is like "crying wolf", eventually people will start ignoring 'const' because it's all over the place and means nothing most of the time.
API 中不需要的太多“const”就像“狼来了”,最终人们会开始忽略“const”,因为它无处不在,而且大多数时候毫无意义。
The "reductio ad absurdum" argument to extra consts in API are good for these first two points would be is if more const parameters are good, then every argument that can have a const on it, SHOULD have a const on it. In fact, if it were truly that good, you'd want const to be the default for parameters and have a keyword like "mutable" only when you want to change the parameter.
API 中额外常量的“reductio ad absurdum”参数对前两点有好处,那就是如果更多的 const 参数是好的,那么每个可以有 const 的参数都应该有一个 const 。事实上,如果它真的那么好,你会希望 const 成为参数的默认值,并且只有当你想要更改参数时才使用像“mutable”这样的关键字。
So lets try putting in const whereever we can:
因此,让我们尝试在任何可能的地方输入 const:
void mungerum(char * buffer, const char * mask, int count);
void mungerum(char * const buffer, const char * const mask, const int count);
Consider the line of code above. Not only is the declaration more cluttered and longer and harder to read but three of the four 'const' keywords can be safely ignored by the API user. However, the extra use of 'const' has made the second line potentially DANGEROUS!
考虑上面的代码行。不仅声明更混乱、更长、更难阅读,而且 API 用户可以安全地忽略四个“const”关键字中的三个。然而,'const' 的额外使用使得第二行可能是危险的!
Why?
为什么?
A quick misread of the first parameter char * const buffer
might make you think that it will not modify the memory in data buffer that is passed in -- however, this is not true! Superfluous 'const' can lead to dangerous and incorrect assumptions about your APIwhen scanned or misread quickly.
对第一个参数的快速误读char * const buffer
可能会让您认为它不会修改传入的数据缓冲区中的内存——然而,事实并非如此!当快速扫描或误读时,多余的“const”可能会导致对 API 的危险和错误假设。
Superfluous const are bad from a Code Implementation stand-point as well:
从代码实现的角度来看,多余的 const 也是不好的:
#if FLEXIBLE_IMPLEMENTATION
#define SUPERFLUOUS_CONST
#else
#define SUPERFLUOUS_CONST const
#endif
void bytecopy(char * SUPERFLUOUS_CONST dest,
const char *source, SUPERFLUOUS_CONST int count);
If FLEXIBLE_IMPLEMENTATION is not true, then the API is “promising” not to implement the function the first way below.
如果 FLEXIBLE_IMPLEMENTATION 不为真,那么 API 就“承诺”不会以下面的第一种方式实现该功能。
void bytecopy(char * SUPERFLUOUS_CONST dest,
const char *source, SUPERFLUOUS_CONST int count)
{
// Will break if !FLEXIBLE_IMPLEMENTATION
while(count--)
{
*dest++=*source++;
}
}
void bytecopy(char * SUPERFLUOUS_CONST dest,
const char *source, SUPERFLUOUS_CONST int count)
{
for(int i=0;i<count;i++)
{
dest[i]=source[i];
}
}
That's a very silly promise to make. Why should you make a promise that gives no benefit at all to your caller and only limits your implementation?
这是一个非常愚蠢的承诺。为什么你要做出一个对调用者没有任何好处而只会限制你的实现的承诺?
Both of these are perfectly valid implementations of the same function though so all you've done is tied one hand behind your back unnecessarily.
这两个都是相同功能的完全有效的实现,所以你所做的一切都是不必要地将一只手绑在背后。
Furthermore, it's a very shallow promise that is easily (and legally circumvented).
此外,这是一个非常肤浅的承诺,很容易(并且在法律上可以规避)。
inline void bytecopyWrapped(char * dest,
const char *source, int count)
{
while(count--)
{
*dest++=*source++;
}
}
void bytecopy(char * SUPERFLUOUS_CONST dest,
const char *source,SUPERFLUOUS_CONST int count)
{
bytecopyWrapped(dest, source, count);
}
Look, I implemented it that way anyhow even though I promised not to – just using a wrapper function. It's like when the bad guy promises not to kill someone in a movie and orders his henchman to kill them instead.
看,无论如何我都以这种方式实现了它,尽管我承诺不会 - 只是使用包装函数。这就像电影中的坏人承诺不会杀死某人并命令他的心腹杀死他们一样。
Those superfluous const's are worth no more than a promise from a movie bad-guy.
那些多余的常量值不过是电影坏人的承诺。
But the ability to lie gets even worse:
但是说谎的能力变得更糟:
I have been enlightened that you can mismatch const in header (declaration) and code (definition) by using spurious const. The const-happy advocates claim this is a good thing since it lets you put const only in the definition.
我已经意识到您可以通过使用虚假常量来使标头(声明)和代码(定义)中的常量不匹配。const-happy 拥护者声称这是一件好事,因为它允许您只将 const 放在定义中。
// Example of const only in definition, not declaration
class foo { void test(int *pi); };
void foo::test(int * const pi) { }
However, the converse is true... you can put a spurious const only in the declaration and ignore it in the definition. This only makes superfluous const in an API more of a terrible thing and a horrible lie - see this example:
然而,反之亦然……你可以只在声明中放置一个虚假的常量,而在定义中忽略它。这只会使 API 中多余的 const 变得更加可怕和可怕的谎言 - 请参见以下示例:
class foo
{
void test(int * const pi);
};
void foo::test(int *pi) // Look, the const in the definition is so superfluous I can ignore it here
{
pi++; // I promised in my definition I wouldn't modify this
}
All the superfluous const actually does is make the implementer's code less readable by forcing him to use another local copy or a wrapper function when he wants to change the variable or pass the variable by non-const reference.
所有多余的 const 实际所做的就是在实现者想要更改变量或通过非常量引用传递变量时强制他使用另一个本地副本或包装函数,从而降低实现者的代码的可读性。
Look at this example. Which is more readable ? Is it obvious that the only reason for the extra variable in the second function is because some API designer threw in a superfluous const ?
看看这个例子。哪个更具可读性?很明显,第二个函数中额外变量的唯一原因是因为某些 API 设计者加入了一个多余的 const 吗?
struct llist
{
llist * next;
};
void walkllist(llist *plist)
{
llist *pnext;
while(plist)
{
pnext=plist->next;
walk(plist);
plist=pnext; // This line wouldn't compile if plist was const
}
}
void walkllist(llist * SUPERFLUOUS_CONST plist)
{
llist * pnotconst=plist;
llist *pnext;
while(pnotconst)
{
pnext=pnotconst->next;
walk(pnotconst);
pnotconst=pnext;
}
}
Hopefully we've learned something here. Superfluous const is an API-cluttering eyesore, an annoying nag, a shallow and meaningless promise, an unnecessary hindrance, and occasionally leads to very dangerous mistakes.
希望我们在这里学到了一些东西。多余的 const 是 API 混乱的眼中钉、烦人的唠叨、肤浅而毫无意义的承诺、不必要的障碍,偶尔会导致非常危险的错误。
回答by QBziZ
const should have been the default in C++. Like this :
const 应该是 C++ 中的默认值。像这样 :
int i = 5 ; // i is a constant
var int i = 5 ; // i is a real variable
回答by Avdi
When I coded C++ for a living I consted everything I possibly could. Using const is a great way to help the compiler help you. For instance, const-ing your method return values can save you from typos such as:
当我以编写 C++ 为生时,我竭尽所能。使用 const 是帮助编译器帮助您的好方法。例如,const-ing 你的方法返回值可以避免打字错误,例如:
foo() = 42
when you meant:
当你的意思是:
foo() == 42
If foo() is defined to return a non-const reference:
如果 foo() 被定义为返回非常量引用:
int& foo() { /* ... */ }
The compiler will happily let you assign a value to the anonymous temporary returned by the function call. Making it const:
编译器很乐意让您为函数调用返回的匿名临时值赋值。使其成为常量:
const int& foo() { /* ... */ }
Eliminates this possibility.
消除了这种可能性。
回答by Void
回答by Void
I say const your value parameters.
我说 const 你的值参数。
Consider this buggy function:
考虑这个有问题的函数:
bool isZero(int number)
{
if (number = 0) // whoops, should be number == 0
return true;
else
return false;
}
If the number parameter was const, the compiler would stop and warn us of the bug.
如果 number 参数是 const,编译器会停止并警告我们这个错误。
回答by Asaf R
I use const on function parameters that are references (or pointers) which are only [in] data and will not be modified by the function. Meaning, when the purpose of using a reference is to avoid copying data and not to allow changing the passed parameter.
我在作为引用(或指针)的函数参数上使用 const ,这些参数只是 [in] 数据并且不会被函数修改。意思是,当使用引用的目的是避免复制数据并且不允许更改传递的参数时。
Putting const on the boolean b parameter in your example only puts a constraint on the implementation and doesn't contribute for the class's interface (although not changing parameters is usually advised).
在您的示例中将 const 放在布尔 b 参数上只会对实现施加约束,并且不会对类的接口做出贡献(尽管通常建议不要更改参数)。
The function signature for
函数签名为
void foo(int a);
and
和
void foo(const int a);
is the same, which explains your .c and .h
是一样的,这解释了你的 .c 和 .h
Asaf
阿萨夫