使用“const”函数参数。

时间:2022-07-25 18:00:07

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 ?例如,假设有一个简单的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?

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

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.

这是有原因的吗?我觉得这有点不寻常。

30 个解决方案

#1


135  

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,但当它在某个东西上循环时,我不打算修改它,所以我想,只要对引用类型进行严格维护,就可以对每个对象进行修改。

#2


327  

"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 might help the compiler optimize things a bit (though it's a long shot).

此外,正如前面提到的,它可能有助于编译器优化一些东西(尽管它是一个很长的镜头)。

#3


114  

Sometimes (too often!) I have to untangle someone else's C++ code. And we all know that someone else's C++ code is a complete mess almost by definition :) So the first thing I do to decipher local data flow is put const in 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,直到编译器开始吠叫。这也意味着符合条件的值参数,因为它们只是调用者初始化的本地变量。

Ah, I wish variables were const by default and mutable was required for non-const variables :)

啊,我希望变量默认为const,而非const变量则需要可变。)

#4


64  

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.

显然,如果定义了第二种方法,你将无法修改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可以取一个很大的参数,可能是一个大小为gb的数据结构,而不需要复制它。另外,它对调用者说,“Foo不会改变该参数的内容。”传递一个const引用还允许编译器做出某些性能决定。

*: Unless it casts away the const-ness, but that's another post.

*:除非它能驱散人群,但那是另一篇文章。

#5


55  

Extra Superfluous const are bad from an API stand-point:

额外的多余的const从API的角度来看是不好的:

Putting extra superfluous const's in your code for intrinsic type parameters passed by value clutters your API while making no meaningful promise to the caller or API user (it only hampers the implementation).

将额外的多余的const放在您的代码中,以获得由值传递的固有类型参数,同时对调用者或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中额外的consts的“减少的荒谬”论点是好的。实际上,如果它真的那么好,那么您希望const是参数的默认值,只有在您想要更改参数时才有“可变”的关键字。

So lets try putting in const whereever we can:

所以,让我们试着把我们能做到的东西放在一起:

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!

考虑上面的代码行。不仅仅是声明变得更加混乱,更冗长,更难以阅读,而且四个“const”关键字中的三个可以被API用户安全地忽略。然而,“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 API when scanned or misread quickly.

对第一个参数char * const缓冲区的快速误读可能会使您认为它不会修改传入的数据缓冲区中的内存——然而,这不是真的!多余的“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.

如果flexble_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.

那些多余的const的价值不超过电影《坏小子》的承诺。


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。这是一件好事,因为它只允许你在定义中使用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:

然而,反过来才是真的……您可以只在声明中放入虚假的const,并在定义中忽略它。这只会让多余的const在API中变得更可怕,更可怕的谎言——看这个例子:

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实际上都是使实现者的代码可读性不强,迫使他使用另一个本地副本或包装器函数,当他想要更改变量或通过非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设计器抛出了一个多余的常量?

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是一种杂乱的眼睛,一种烦人的唠叨,一种肤浅而毫无意义的承诺,一种不必要的障碍,偶尔会导致非常危险的错误。

#6


32  

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

#7


25  

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.

消除了这种可能性。

#8


12  

There is a good discussion on this topic in the old "Guru of the Week" articles on comp.lang.c++.moderated here.

在“本周古鲁”的文章中有一个关于这个话题的很好的讨论。主持。

The corresponding GOTW article is available on Herb Sutter's web site here.

在Herb Sutter的网站上有相应的GOTW文章。

#9


7  

I say const your value parameters.

我说的是你的价值参数。

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,编译器会停止并警告我们错误。

#10


7  

If you use the ->* or .* operators, it's a must.

It prevents you from writing something like

它阻止你写类似的东西。

void foo(Bar *p) { if (++p->*member > 0) { ... } }

which I almost did right now, and which probably doesn't do what you intend.

我马上就做了,这可能不符合你的意愿。

What I intended to say was

我想说的是!

void foo(Bar *p) { if (++(p->*member) > 0) { ... } }

and if I had put a const in between Bar * and p, the compiler would have told me that.

如果我把一个const放在Bar *和p之间,编译器会告诉我。

#11


6  

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,这些参数是引用(或指针),它们只是[在]数据中,不会被函数修改。意义,当使用引用的目的是避免复制数据,而不允许更改传递的参数。

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放在boolean 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

Asaf

#12


5  

Ah, a tough one. On one side, a declaration is a contract and it really does not make sense to pass a const argument by value. On the other hand, if you look at the function implementation, you give the compiler more chances to optimize if you declare an argument constant.

啊,很艰难。一方面,声明是一种契约,通过价值传递一个const参数是没有意义的。另一方面,如果查看函数实现,如果您声明一个参数常量,则会给编译器提供更多的优化机会。

#13


4  

const is pointless when the argument is passed by value since you will not be modifying the caller's object.

当参数通过值传递时,const是无意义的,因为您不会修改调用者的对象。

const should be preferred when passing by reference, unless the purpose of the function is to modify the passed value.

当通过引用时,应该首选const,除非函数的目的是修改已传递的值。

Finally, a function which does not modify current object (this) can, and probably should be declared const. An example is below:

最后,一个不修改当前对象(这个)的函数可以,并且应该被声明为const。下面就是一个例子:

int SomeClass::GetValue() const {return m_internalValue;}

This is a promise to not modify the object to which this call is applied. In other words, you can call:

这是一个承诺,不修改这个调用所应用的对象。换句话说,你可以打电话:

const SomeClass* pSomeClass;
pSomeClass->GetValue();

If the function was not const, this would result in a compiler warning.

如果函数不是常量,这将导致编译器警告。

#14


4  

Marking value parameters 'const' is definitely a subjective thing.

标记值参数“const”绝对是一件主观的事情。

However I actually prefer to mark value parameters const, just like in your example.

然而,我实际上更喜欢标记值参数const,就像在您的示例中一样。

void func(const int n, const long l) { /* ... */ }

The value to me is in clearly indicating that the function parameter values are never changed by the function. They will have the same value at the beginning as at the end. For me, it is part of keeping to a very functional programming sort of style.

对我来说,它的值是清楚地表明函数参数值不会被函数改变。在开始时,它们的值是相同的。对我来说,它是一种非常实用的编程风格的一部分。

For a short function, it's arguably a waste of time/space to have the 'const' there, since it's usually pretty obvious that the arguments aren't modified by the function.

对于一个简短的函数,它可能是浪费时间/空间来获得“const”,因为通常很明显,参数没有被函数修改。

However for a larger function, its a form of implementation documentation, and it is enforced by the compiler.

然而,对于更大的函数,它是一种实现文档,由编译器强制执行。

I can be sure if I make some computation with 'n' and 'l', I can refactor/move that computation without fear of getting a different result because I missed a place where one or both is changed.

我可以确定如果我用'n'和'l'做一些计算,我可以重构/移动那个计算而不用担心会得到一个不同的结果,因为我错过了一个或者两者都变了的地方。

Since it is an implementation detail, you don't need to declare the value parameters const in the header, just like you don't need to declare the function parameters with the same names as the implementation uses.

由于它是一个实现细节,所以您不需要在header中声明值参数const,就像您不需要使用与实现使用相同的名称来声明函数参数一样。

#15


2  

In the case you mention, it doesn't affect callers of your API, which is why it's not commonly done (and isn't necessary in the header). It only affects the implementation of your function.

在您提到的情况下,它不会影响您的API的调用者,这就是为什么它不常见(在header中不需要)。它只影响函数的实现。

It's not particularly a bad thing to do, but the benefits aren't that great given that it doesn't affect your API, and it adds typing, so it's not usually done.

这并不是一件坏事,但它的好处并不大,因为它不会影响你的API,而且它会增加输入,所以通常不会这么做。

#16


2  

I do not use const for value-passed parametere. The caller does not care whether you modify the parameter or not, it's an implementation detail.

我不使用const作为值传递的parametere。调用者并不关心您是否修改了参数,这是一个实现细节。

What is really important is to mark methods as const if they do not modify their instance. Do this as you go, because otherwise you might end up with either lots of const_cast<> or you might find that marking a method const requires changing a lot of code because it calls other methods which should have been marked const.

真正重要的是将方法标记为const,如果它们不修改它们的实例。您可以这样做,否则您可能会得到很多const_cast<>,或者您可能会发现,标记一个方法const需要更改很多代码,因为它调用了其他应该标记为const的方法。

I also tend to mark local vars const if I do not need to modify them. I believe it makes the code easier to understand by making it easier to identify the "moving parts".

如果不需要修改,我也倾向于标记本地的vars const。我认为,通过使识别“活动部件”更容易,使代码更容易理解。

#17


2  

I tend to use const wherever possible. (Or other appropriate keyword for the target language.) I do this purely because it allows the compiler to make extra optimizations that it would not be able to make otherwise. Since I have no idea what these optimizations may be, I always do it, even where it seems silly.

我倾向于尽可能使用const。(或其他适合于目标语言的关键字。)我这样做纯粹是因为它允许编译器进行额外的优化,否则它将无法进行其他优化。因为我不知道这些优化可能是什么,我总是这样做,即使在它看起来很傻的地方。

For all I know, the compiler might very well see a const value parameter, and say, "Hey, this function isn't modifying it anyway, so I can pass by reference and save some clock cycles." I don't think it ever would do such a thing, since it changes the function signature, but it makes the point. Maybe it does some different stack manipulation or something... The point is, I don't know, but I do know trying to be smarter than the compiler only leads to me being shamed.

据我所知,编译器很可能会看到一个const值参数,然后说,“嘿,这个函数没有修改它,所以我可以通过引用来传递,并保存一些时钟周期。”我不认为它会做这样的事情,因为它改变了函数签名,但它说明了问题。也许它会做一些不同的堆栈操作…重点是,我不知道,但我知道,试图比编译器聪明,只会让我感到羞愧。

C++ has some extra baggage, with the idea of const-correctness, so it becomes even more important.

c++有一些额外的行李,有了“const-正确性”的概念,所以它变得更加重要。

#18


2  

I use const were I can. Const for parameters means that they should not change their value. This is especially valuable when passing by reference. const for function declares that the function should not change the classes members.

我用的是const。参数Const意味着它们不应该改变其值。这在通过引用时特别有用。函数的const声明函数不应该更改类成员。

#19


2  

May be this wont be a valid argument. but if we increment the value of a const variable inside a function compiler will give us an error: "error: increment of read-only parameter". so that means we can use const key word as a way to prevent accidentally modifying our variables inside functions(which we are not supposed to/read-only). so if we accidentally did it at the compile time compiler will let us know that. this is specially important if you are not the only one who is working on this project.

也许这不是一个有效的论点。但是,如果我们在函数编译器中增加一个const变量的值,就会给我们一个错误:“错误:只读参数的增量”。因此,这意味着我们可以使用const关键词作为防止意外修改函数内部变量(我们不应该/只读)的方法。如果我们在编译时不小心做了它会让我们知道。如果你不是唯一一个在做这个项目的人,这一点特别重要。

#20


1  

Const parameter is useful only when the parameter is passed by reference i.e., either reference or pointer. When compiler sees a const parameter, it make sure that the variable used in the parameter is not modified within the body of the function. Why would anyone want to make a by-value parameter as constant? :-)

只有当参数通过引用传递时,Const参数才有用。,无论是引用还是指针。当编译器看到const参数时,它会确保参数中使用的变量不会在函数体中进行修改。为什么会有人想把一个副值作为常数呢?:-)

#21


1  

If the parameter is passed by value (and is not a reference), usually there is not much difference whether the parameter is declared as const or not (unless it contains a reference member -- not a problem for built-in types). If the parameter is a reference or pointer, it is usually better to protect the referenced/pointed-to memory, not the pointer itself (I think you cannot make the reference itself const, not that it matters much as you cannot change the referee). It seems a good idea to protect everything you can as const. You can omit it without fear of making a mistake if the parameters are just PODs (including built-in types) and there is no chance of them changing further along the road (e.g. in your example the bool parameter).

如果参数是通过值传递的(而不是引用),那么是否将参数声明为const(除非它包含一个引用成员——而不是内置类型的问题),通常没有多大差别。如果参数是引用或指针,通常最好是保护被引用的/指向内存,而不是指针本身(我认为您不能使引用本身成为常量,而不是因为您不能更改仲裁)。保护你所能做的一切似乎是个好主意。如果参数仅仅是pod(包括内置类型),那么您可以忽略它,如果参数只是PODs(包括内置类型),那么它们就不可能在路上进一步更改(例如,在您的示例中bool参数)。

I didn't know about the .h/.cpp file declaration difference, but it does make some sense. At the machine code level, nothing is "const", so if you declare a function (in the .h) as non-const, the code is the same as if you declare it as const (optimizations aside). However, it helps you to enlist the compiler that you will not change the value of the variable inside the implementation of the function (.ccp). It might come handy in the case when you're inheriting from an interface that allows change, but you don't need to change to parameter to achieve the required functionality.

我不知道。h/。cpp文件声明的区别,但它确实有一定的意义。在机器代码级别,没有什么是“const”,所以如果您将一个函数(在.h)中声明为非const,那么代码就等同于您将其声明为const(除了优化之外)。但是,它可以帮助您获得编译器,您不会更改函数的实现中变量的值(.ccp)。当您从允许更改的接口继承时,它可能会很方便,但是您不需要更改为参数来实现所需的功能。

#22


1  

On compiler optimizations: http://www.gotw.ca/gotw/081.htm

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

#23


1  

To summarize:

总结:

  • "Normally const pass-by-value is unuseful and misleading at best." From GOTW006
  • “通常情况下,按价值计算是毫无用处的,而且是误导性的。”从GOTW006
  • But you can add them in the .cpp as you would do with variables.
  • 但是你可以把它们添加到。cpp中,就像你用变量做的那样。
  • Note that the standard library doesn't use const. E.g. std::vector::at(size_type pos). What's good enough for the standard library is good for me.
  • 注意,标准库不使用const。例如std::向量::在(size_type pos)。对标准的图书馆来说,什么是足够好的,对我有好处。

#24


0  

I wouldn't put const on parameters like that - everyone already knows that a boolean (as opposed to a boolean&) is constant, so adding it in will make people think "wait, what?" or even that you're passing the parameter by reference.

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

#25


0  

the thing to remember with const is that it is much easier to make things const from the start, than it is to try and put them in later.

与const相比,要记住的是,从一开始就把事情弄清楚要容易得多,而不是把它们放在后面。

Use const when you want something to be unchanged - its an added hint that describes what your function does and what to expect. I've seen many an C API that could do with some of them, especially ones that accept c-strings!

当你想要一些东西保持不变时,使用const——它是一个附加的提示,它描述了你的功能和期望的功能。我已经看到了许多C API可以处理其中的一些,特别是那些接受C -strings的API !

I'd be more inclined to omit the const keyword in the cpp file than the header, but as I tend to cut+paste them, they'd be kept in both places. I have no idea why the compiler allows that, I guess its a compiler thing. Best practice is definitely to put your const keyword in both files.

我更倾向于忽略cpp文件中的const关键字,而不是header,但是当我倾向于剪切+粘贴它们时,它们会被保存在两个地方。我不知道为什么编译器允许它,我猜它是编译器的东西。最好的做法是把const关键字放在两个文件中。

#26


0  

There's really no reason to make a value-parameter "const" as the function can only modify a copy of the variable anyway.

由于函数只能修改变量的副本,所以没有必要将值参数“const”作为函数。

The reason to use "const" is if you're passing something bigger (e.g. a struct with lots of members) by reference, in which case it ensures that the function can't modify it; or rather, the compiler will complain if you try to modify it in the conventional way. It prevents it from being accidentally modified.

使用“const”的原因是,如果你通过引用传递了更大的东西(例如一个有很多成员的结构),在这种情况下,它确保了函数不能修改它;或者更确切地说,如果你试图用传统的方式修改编译器,编译器会抱怨。它防止意外修改。

#27


0  

As parameters are being passed by value,it doesnt make any difference if you specify const or not from the calling function's perspective.It basically does not make any sense to declare pass by value parameters as const.

由于参数是按值传递的,如果您指定const或不从调用函数的角度来指定const,则没有任何区别。它基本上没有任何意义来声明通过值参数作为const。

#28


0  

All the consts in your examples have no purpose. C++ is pass-by-value by default, so the function gets copies of those ints and booleans. Even if the function does modify them, the caller's copy is not affected.

在你的例子中,所有的困惑都没有目的。在默认情况下,c++是按值传递的,所以函数会得到那些ints和布尔值的副本。即使函数确实修改了它们,调用方的副本也不会受到影响。

So I'd avoid extra consts because

所以我会避免额外的麻烦,因为。

  • They're redudant
  • 他们redudant
  • They clutter up the text
  • 他们把课文弄得乱七八糟。
  • They prevent me from changing the passed in value in cases where it might be useful or efficient.
  • 它们阻止我在可能有用或有效的情况下改变传递的值。

#29


0  

I know the question is "a bit" outdated but as I came accross it somebody else may also do so in future... ...still I doubt the poor fellow will list down here to read my comment :)

我知道这个问题有点过时了,但是当我遇到这个问题的时候,其他人也会这样做……我仍然怀疑这个可怜的家伙是否会在这里写下我的评论:)

It seems to me that we are still too confined to C-style way of thinking. In the OOP paradigma we play around with objects, not types. Const object may be conceptually different from a non-const object, specifically in the sense of logical-const (in contrast to bitwise-const). Thus even if const correctness of function params is (perhaps) an over-carefulness in case of PODs it is not so in case of objects. If a function works with a const object it should say so. Consider the following code snippet

在我看来,我们仍然太局限于c风格的思维方式。在OOP范式中,我们使用对象,而不是类型。Const对象可能在概念上不同于非Const对象,特别是在逻辑- Const(与bitwise-const相反)的意义上。因此,即使函数params的const正确性(也许)是一个过度谨慎的例子,但在对象的情况下不是这样的。如果一个函数与一个const对象一起工作,它应该这样说。考虑下面的代码片段。

#include <iostream>

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class SharedBuffer {
private:

  int fakeData;

  int const & Get_(int i) const
  {

    std::cout << "Accessing buffer element" << std::endl;
    return fakeData;

  }

public:

  int & operator[](int i)
  {

    Unique();
    return const_cast<int &>(Get_(i));

  }

  int const & operator[](int i) const
  {

    return Get_(i);

  }

  void Unique()
  {

    std::cout << "Making buffer unique (expensive operation)" << std::endl;

  }

};

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void NonConstF(SharedBuffer x)
{

  x[0] = 1;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ConstF(const SharedBuffer x)
{

  int q = x[0];

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int main()
{

  SharedBuffer x;

  NonConstF(x);

  std::cout << std::endl;

  ConstF(x);

  return 0;

}

ps.: you may argue that (const) reference would be more appropriate here and gives you the same behaviour. Well, right. Just giving a different picture from what I could see elsewhere...

ps:你可能会认为(const)引用在这里更合适,也会给你同样的行为。嗯,对的。只是给我一个不同的画面,从我在其他地方看到的…

#30


-1  

Being a VB.NET programmer that needs to use a C++ program with 50+ exposed functions, and a .h file that sporadically uses the const qualifier, it is difficult to know when to access a variable using ByRef or ByVal.

一个VB。NET程序员需要使用一个具有50多个公开功能的c++程序和一个.h文件,它偶尔使用const限定符,因此很难知道何时使用ByRef或ByVal访问变量。

Of course the program tells you by generating an exception error on the line where you made the mistake, but then you need to guess which of the 2-10 parameters is wrong.

当然,程序通过在错误的地方生成一个异常错误来告诉您,但是接下来您需要猜出2-10个参数中哪一个是错误的。

So now I have the distasteful task of trying to convince a developer that they should really define their variables (in the .h file) in a manner that allows an automated method of creating all of the VB.NET function definitions easily. They will then smugly say, "read the ... documentation."

因此,现在我有一项令人厌恶的任务,即试图说服开发人员,他们应该以一种允许自动创建所有VB的方式来定义他们的变量(在.h文件中)。净函数定义。他们会沾沾自喜地说:“读……”文档”。

I have written an awk script that parses a .h file, and creates all of the Declare Function commands, but without an indicator as to which variables are R/O vs R/W, it only does half the job.

我已经编写了一个awk脚本,它解析了一个.h文件,并创建了所有的声明函数命令,但是没有一个指示变量是R/O vs R/W的指示器,它只做了一半的工作。

EDIT:

编辑:

At the encouragement of another user I am adding the following;

在另一个用户的鼓励下,我添加了以下内容;

Here is an example of a (IMO) poorly formed .h entry;

这里有一个(IMO)格式差的例子。

typedef int (EE_STDCALL *Do_SomethingPtr)( int smfID, const char* cursor_name, const char* sql );

The resultant VB from my script;

从我的脚本生成的VB;

    Declare Function Do_Something Lib "SomeOther.DLL" (ByRef smfID As Integer, ByVal cursor_name As String, ByVal sql As String) As Integer

Note the missing "const" on the first parameter. Without it, a program (or another developer) has no Idea the 1st parameter should be passed "ByVal." By adding the "const" it makes the .h file self documenting so that developers using other languages can easily write working code.

请注意第一个参数中缺少的“const”。没有它,程序(或其他开发人员)不知道第一个参数应该通过“ByVal”。通过添加“const”,它使.h文件自文档化,以便使用其他语言的开发人员可以轻松地编写工作代码。

#1


135  

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,但当它在某个东西上循环时,我不打算修改它,所以我想,只要对引用类型进行严格维护,就可以对每个对象进行修改。

#2


327  

"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 might help the compiler optimize things a bit (though it's a long shot).

此外,正如前面提到的,它可能有助于编译器优化一些东西(尽管它是一个很长的镜头)。

#3


114  

Sometimes (too often!) I have to untangle someone else's C++ code. And we all know that someone else's C++ code is a complete mess almost by definition :) So the first thing I do to decipher local data flow is put const in 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,直到编译器开始吠叫。这也意味着符合条件的值参数,因为它们只是调用者初始化的本地变量。

Ah, I wish variables were const by default and mutable was required for non-const variables :)

啊,我希望变量默认为const,而非const变量则需要可变。)

#4


64  

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.

显然,如果定义了第二种方法,你将无法修改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可以取一个很大的参数,可能是一个大小为gb的数据结构,而不需要复制它。另外,它对调用者说,“Foo不会改变该参数的内容。”传递一个const引用还允许编译器做出某些性能决定。

*: Unless it casts away the const-ness, but that's another post.

*:除非它能驱散人群,但那是另一篇文章。

#5


55  

Extra Superfluous const are bad from an API stand-point:

额外的多余的const从API的角度来看是不好的:

Putting extra superfluous const's in your code for intrinsic type parameters passed by value clutters your API while making no meaningful promise to the caller or API user (it only hampers the implementation).

将额外的多余的const放在您的代码中,以获得由值传递的固有类型参数,同时对调用者或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中额外的consts的“减少的荒谬”论点是好的。实际上,如果它真的那么好,那么您希望const是参数的默认值,只有在您想要更改参数时才有“可变”的关键字。

So lets try putting in const whereever we can:

所以,让我们试着把我们能做到的东西放在一起:

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!

考虑上面的代码行。不仅仅是声明变得更加混乱,更冗长,更难以阅读,而且四个“const”关键字中的三个可以被API用户安全地忽略。然而,“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 API when scanned or misread quickly.

对第一个参数char * const缓冲区的快速误读可能会使您认为它不会修改传入的数据缓冲区中的内存——然而,这不是真的!多余的“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.

如果flexble_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.

那些多余的const的价值不超过电影《坏小子》的承诺。


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。这是一件好事,因为它只允许你在定义中使用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:

然而,反过来才是真的……您可以只在声明中放入虚假的const,并在定义中忽略它。这只会让多余的const在API中变得更可怕,更可怕的谎言——看这个例子:

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实际上都是使实现者的代码可读性不强,迫使他使用另一个本地副本或包装器函数,当他想要更改变量或通过非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设计器抛出了一个多余的常量?

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是一种杂乱的眼睛,一种烦人的唠叨,一种肤浅而毫无意义的承诺,一种不必要的障碍,偶尔会导致非常危险的错误。

#6


32  

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

#7


25  

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.

消除了这种可能性。

#8


12  

There is a good discussion on this topic in the old "Guru of the Week" articles on comp.lang.c++.moderated here.

在“本周古鲁”的文章中有一个关于这个话题的很好的讨论。主持。

The corresponding GOTW article is available on Herb Sutter's web site here.

在Herb Sutter的网站上有相应的GOTW文章。

#9


7  

I say const your value parameters.

我说的是你的价值参数。

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,编译器会停止并警告我们错误。

#10


7  

If you use the ->* or .* operators, it's a must.

It prevents you from writing something like

它阻止你写类似的东西。

void foo(Bar *p) { if (++p->*member > 0) { ... } }

which I almost did right now, and which probably doesn't do what you intend.

我马上就做了,这可能不符合你的意愿。

What I intended to say was

我想说的是!

void foo(Bar *p) { if (++(p->*member) > 0) { ... } }

and if I had put a const in between Bar * and p, the compiler would have told me that.

如果我把一个const放在Bar *和p之间,编译器会告诉我。

#11


6  

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,这些参数是引用(或指针),它们只是[在]数据中,不会被函数修改。意义,当使用引用的目的是避免复制数据,而不允许更改传递的参数。

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放在boolean 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

Asaf

#12


5  

Ah, a tough one. On one side, a declaration is a contract and it really does not make sense to pass a const argument by value. On the other hand, if you look at the function implementation, you give the compiler more chances to optimize if you declare an argument constant.

啊,很艰难。一方面,声明是一种契约,通过价值传递一个const参数是没有意义的。另一方面,如果查看函数实现,如果您声明一个参数常量,则会给编译器提供更多的优化机会。

#13


4  

const is pointless when the argument is passed by value since you will not be modifying the caller's object.

当参数通过值传递时,const是无意义的,因为您不会修改调用者的对象。

const should be preferred when passing by reference, unless the purpose of the function is to modify the passed value.

当通过引用时,应该首选const,除非函数的目的是修改已传递的值。

Finally, a function which does not modify current object (this) can, and probably should be declared const. An example is below:

最后,一个不修改当前对象(这个)的函数可以,并且应该被声明为const。下面就是一个例子:

int SomeClass::GetValue() const {return m_internalValue;}

This is a promise to not modify the object to which this call is applied. In other words, you can call:

这是一个承诺,不修改这个调用所应用的对象。换句话说,你可以打电话:

const SomeClass* pSomeClass;
pSomeClass->GetValue();

If the function was not const, this would result in a compiler warning.

如果函数不是常量,这将导致编译器警告。

#14


4  

Marking value parameters 'const' is definitely a subjective thing.

标记值参数“const”绝对是一件主观的事情。

However I actually prefer to mark value parameters const, just like in your example.

然而,我实际上更喜欢标记值参数const,就像在您的示例中一样。

void func(const int n, const long l) { /* ... */ }

The value to me is in clearly indicating that the function parameter values are never changed by the function. They will have the same value at the beginning as at the end. For me, it is part of keeping to a very functional programming sort of style.

对我来说,它的值是清楚地表明函数参数值不会被函数改变。在开始时,它们的值是相同的。对我来说,它是一种非常实用的编程风格的一部分。

For a short function, it's arguably a waste of time/space to have the 'const' there, since it's usually pretty obvious that the arguments aren't modified by the function.

对于一个简短的函数,它可能是浪费时间/空间来获得“const”,因为通常很明显,参数没有被函数修改。

However for a larger function, its a form of implementation documentation, and it is enforced by the compiler.

然而,对于更大的函数,它是一种实现文档,由编译器强制执行。

I can be sure if I make some computation with 'n' and 'l', I can refactor/move that computation without fear of getting a different result because I missed a place where one or both is changed.

我可以确定如果我用'n'和'l'做一些计算,我可以重构/移动那个计算而不用担心会得到一个不同的结果,因为我错过了一个或者两者都变了的地方。

Since it is an implementation detail, you don't need to declare the value parameters const in the header, just like you don't need to declare the function parameters with the same names as the implementation uses.

由于它是一个实现细节,所以您不需要在header中声明值参数const,就像您不需要使用与实现使用相同的名称来声明函数参数一样。

#15


2  

In the case you mention, it doesn't affect callers of your API, which is why it's not commonly done (and isn't necessary in the header). It only affects the implementation of your function.

在您提到的情况下,它不会影响您的API的调用者,这就是为什么它不常见(在header中不需要)。它只影响函数的实现。

It's not particularly a bad thing to do, but the benefits aren't that great given that it doesn't affect your API, and it adds typing, so it's not usually done.

这并不是一件坏事,但它的好处并不大,因为它不会影响你的API,而且它会增加输入,所以通常不会这么做。

#16


2  

I do not use const for value-passed parametere. The caller does not care whether you modify the parameter or not, it's an implementation detail.

我不使用const作为值传递的parametere。调用者并不关心您是否修改了参数,这是一个实现细节。

What is really important is to mark methods as const if they do not modify their instance. Do this as you go, because otherwise you might end up with either lots of const_cast<> or you might find that marking a method const requires changing a lot of code because it calls other methods which should have been marked const.

真正重要的是将方法标记为const,如果它们不修改它们的实例。您可以这样做,否则您可能会得到很多const_cast<>,或者您可能会发现,标记一个方法const需要更改很多代码,因为它调用了其他应该标记为const的方法。

I also tend to mark local vars const if I do not need to modify them. I believe it makes the code easier to understand by making it easier to identify the "moving parts".

如果不需要修改,我也倾向于标记本地的vars const。我认为,通过使识别“活动部件”更容易,使代码更容易理解。

#17


2  

I tend to use const wherever possible. (Or other appropriate keyword for the target language.) I do this purely because it allows the compiler to make extra optimizations that it would not be able to make otherwise. Since I have no idea what these optimizations may be, I always do it, even where it seems silly.

我倾向于尽可能使用const。(或其他适合于目标语言的关键字。)我这样做纯粹是因为它允许编译器进行额外的优化,否则它将无法进行其他优化。因为我不知道这些优化可能是什么,我总是这样做,即使在它看起来很傻的地方。

For all I know, the compiler might very well see a const value parameter, and say, "Hey, this function isn't modifying it anyway, so I can pass by reference and save some clock cycles." I don't think it ever would do such a thing, since it changes the function signature, but it makes the point. Maybe it does some different stack manipulation or something... The point is, I don't know, but I do know trying to be smarter than the compiler only leads to me being shamed.

据我所知,编译器很可能会看到一个const值参数,然后说,“嘿,这个函数没有修改它,所以我可以通过引用来传递,并保存一些时钟周期。”我不认为它会做这样的事情,因为它改变了函数签名,但它说明了问题。也许它会做一些不同的堆栈操作…重点是,我不知道,但我知道,试图比编译器聪明,只会让我感到羞愧。

C++ has some extra baggage, with the idea of const-correctness, so it becomes even more important.

c++有一些额外的行李,有了“const-正确性”的概念,所以它变得更加重要。

#18


2  

I use const were I can. Const for parameters means that they should not change their value. This is especially valuable when passing by reference. const for function declares that the function should not change the classes members.

我用的是const。参数Const意味着它们不应该改变其值。这在通过引用时特别有用。函数的const声明函数不应该更改类成员。

#19


2  

May be this wont be a valid argument. but if we increment the value of a const variable inside a function compiler will give us an error: "error: increment of read-only parameter". so that means we can use const key word as a way to prevent accidentally modifying our variables inside functions(which we are not supposed to/read-only). so if we accidentally did it at the compile time compiler will let us know that. this is specially important if you are not the only one who is working on this project.

也许这不是一个有效的论点。但是,如果我们在函数编译器中增加一个const变量的值,就会给我们一个错误:“错误:只读参数的增量”。因此,这意味着我们可以使用const关键词作为防止意外修改函数内部变量(我们不应该/只读)的方法。如果我们在编译时不小心做了它会让我们知道。如果你不是唯一一个在做这个项目的人,这一点特别重要。

#20


1  

Const parameter is useful only when the parameter is passed by reference i.e., either reference or pointer. When compiler sees a const parameter, it make sure that the variable used in the parameter is not modified within the body of the function. Why would anyone want to make a by-value parameter as constant? :-)

只有当参数通过引用传递时,Const参数才有用。,无论是引用还是指针。当编译器看到const参数时,它会确保参数中使用的变量不会在函数体中进行修改。为什么会有人想把一个副值作为常数呢?:-)

#21


1  

If the parameter is passed by value (and is not a reference), usually there is not much difference whether the parameter is declared as const or not (unless it contains a reference member -- not a problem for built-in types). If the parameter is a reference or pointer, it is usually better to protect the referenced/pointed-to memory, not the pointer itself (I think you cannot make the reference itself const, not that it matters much as you cannot change the referee). It seems a good idea to protect everything you can as const. You can omit it without fear of making a mistake if the parameters are just PODs (including built-in types) and there is no chance of them changing further along the road (e.g. in your example the bool parameter).

如果参数是通过值传递的(而不是引用),那么是否将参数声明为const(除非它包含一个引用成员——而不是内置类型的问题),通常没有多大差别。如果参数是引用或指针,通常最好是保护被引用的/指向内存,而不是指针本身(我认为您不能使引用本身成为常量,而不是因为您不能更改仲裁)。保护你所能做的一切似乎是个好主意。如果参数仅仅是pod(包括内置类型),那么您可以忽略它,如果参数只是PODs(包括内置类型),那么它们就不可能在路上进一步更改(例如,在您的示例中bool参数)。

I didn't know about the .h/.cpp file declaration difference, but it does make some sense. At the machine code level, nothing is "const", so if you declare a function (in the .h) as non-const, the code is the same as if you declare it as const (optimizations aside). However, it helps you to enlist the compiler that you will not change the value of the variable inside the implementation of the function (.ccp). It might come handy in the case when you're inheriting from an interface that allows change, but you don't need to change to parameter to achieve the required functionality.

我不知道。h/。cpp文件声明的区别,但它确实有一定的意义。在机器代码级别,没有什么是“const”,所以如果您将一个函数(在.h)中声明为非const,那么代码就等同于您将其声明为const(除了优化之外)。但是,它可以帮助您获得编译器,您不会更改函数的实现中变量的值(.ccp)。当您从允许更改的接口继承时,它可能会很方便,但是您不需要更改为参数来实现所需的功能。

#22


1  

On compiler optimizations: http://www.gotw.ca/gotw/081.htm

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

#23


1  

To summarize:

总结:

  • "Normally const pass-by-value is unuseful and misleading at best." From GOTW006
  • “通常情况下,按价值计算是毫无用处的,而且是误导性的。”从GOTW006
  • But you can add them in the .cpp as you would do with variables.
  • 但是你可以把它们添加到。cpp中,就像你用变量做的那样。
  • Note that the standard library doesn't use const. E.g. std::vector::at(size_type pos). What's good enough for the standard library is good for me.
  • 注意,标准库不使用const。例如std::向量::在(size_type pos)。对标准的图书馆来说,什么是足够好的,对我有好处。

#24


0  

I wouldn't put const on parameters like that - everyone already knows that a boolean (as opposed to a boolean&) is constant, so adding it in will make people think "wait, what?" or even that you're passing the parameter by reference.

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

#25


0  

the thing to remember with const is that it is much easier to make things const from the start, than it is to try and put them in later.

与const相比,要记住的是,从一开始就把事情弄清楚要容易得多,而不是把它们放在后面。

Use const when you want something to be unchanged - its an added hint that describes what your function does and what to expect. I've seen many an C API that could do with some of them, especially ones that accept c-strings!

当你想要一些东西保持不变时,使用const——它是一个附加的提示,它描述了你的功能和期望的功能。我已经看到了许多C API可以处理其中的一些,特别是那些接受C -strings的API !

I'd be more inclined to omit the const keyword in the cpp file than the header, but as I tend to cut+paste them, they'd be kept in both places. I have no idea why the compiler allows that, I guess its a compiler thing. Best practice is definitely to put your const keyword in both files.

我更倾向于忽略cpp文件中的const关键字,而不是header,但是当我倾向于剪切+粘贴它们时,它们会被保存在两个地方。我不知道为什么编译器允许它,我猜它是编译器的东西。最好的做法是把const关键字放在两个文件中。

#26


0  

There's really no reason to make a value-parameter "const" as the function can only modify a copy of the variable anyway.

由于函数只能修改变量的副本,所以没有必要将值参数“const”作为函数。

The reason to use "const" is if you're passing something bigger (e.g. a struct with lots of members) by reference, in which case it ensures that the function can't modify it; or rather, the compiler will complain if you try to modify it in the conventional way. It prevents it from being accidentally modified.

使用“const”的原因是,如果你通过引用传递了更大的东西(例如一个有很多成员的结构),在这种情况下,它确保了函数不能修改它;或者更确切地说,如果你试图用传统的方式修改编译器,编译器会抱怨。它防止意外修改。

#27


0  

As parameters are being passed by value,it doesnt make any difference if you specify const or not from the calling function's perspective.It basically does not make any sense to declare pass by value parameters as const.

由于参数是按值传递的,如果您指定const或不从调用函数的角度来指定const,则没有任何区别。它基本上没有任何意义来声明通过值参数作为const。

#28


0  

All the consts in your examples have no purpose. C++ is pass-by-value by default, so the function gets copies of those ints and booleans. Even if the function does modify them, the caller's copy is not affected.

在你的例子中,所有的困惑都没有目的。在默认情况下,c++是按值传递的,所以函数会得到那些ints和布尔值的副本。即使函数确实修改了它们,调用方的副本也不会受到影响。

So I'd avoid extra consts because

所以我会避免额外的麻烦,因为。

  • They're redudant
  • 他们redudant
  • They clutter up the text
  • 他们把课文弄得乱七八糟。
  • They prevent me from changing the passed in value in cases where it might be useful or efficient.
  • 它们阻止我在可能有用或有效的情况下改变传递的值。

#29


0  

I know the question is "a bit" outdated but as I came accross it somebody else may also do so in future... ...still I doubt the poor fellow will list down here to read my comment :)

我知道这个问题有点过时了,但是当我遇到这个问题的时候,其他人也会这样做……我仍然怀疑这个可怜的家伙是否会在这里写下我的评论:)

It seems to me that we are still too confined to C-style way of thinking. In the OOP paradigma we play around with objects, not types. Const object may be conceptually different from a non-const object, specifically in the sense of logical-const (in contrast to bitwise-const). Thus even if const correctness of function params is (perhaps) an over-carefulness in case of PODs it is not so in case of objects. If a function works with a const object it should say so. Consider the following code snippet

在我看来,我们仍然太局限于c风格的思维方式。在OOP范式中,我们使用对象,而不是类型。Const对象可能在概念上不同于非Const对象,特别是在逻辑- Const(与bitwise-const相反)的意义上。因此,即使函数params的const正确性(也许)是一个过度谨慎的例子,但在对象的情况下不是这样的。如果一个函数与一个const对象一起工作,它应该这样说。考虑下面的代码片段。

#include <iostream>

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class SharedBuffer {
private:

  int fakeData;

  int const & Get_(int i) const
  {

    std::cout << "Accessing buffer element" << std::endl;
    return fakeData;

  }

public:

  int & operator[](int i)
  {

    Unique();
    return const_cast<int &>(Get_(i));

  }

  int const & operator[](int i) const
  {

    return Get_(i);

  }

  void Unique()
  {

    std::cout << "Making buffer unique (expensive operation)" << std::endl;

  }

};

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void NonConstF(SharedBuffer x)
{

  x[0] = 1;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ConstF(const SharedBuffer x)
{

  int q = x[0];

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int main()
{

  SharedBuffer x;

  NonConstF(x);

  std::cout << std::endl;

  ConstF(x);

  return 0;

}

ps.: you may argue that (const) reference would be more appropriate here and gives you the same behaviour. Well, right. Just giving a different picture from what I could see elsewhere...

ps:你可能会认为(const)引用在这里更合适,也会给你同样的行为。嗯,对的。只是给我一个不同的画面,从我在其他地方看到的…

#30


-1  

Being a VB.NET programmer that needs to use a C++ program with 50+ exposed functions, and a .h file that sporadically uses the const qualifier, it is difficult to know when to access a variable using ByRef or ByVal.

一个VB。NET程序员需要使用一个具有50多个公开功能的c++程序和一个.h文件,它偶尔使用const限定符,因此很难知道何时使用ByRef或ByVal访问变量。

Of course the program tells you by generating an exception error on the line where you made the mistake, but then you need to guess which of the 2-10 parameters is wrong.

当然,程序通过在错误的地方生成一个异常错误来告诉您,但是接下来您需要猜出2-10个参数中哪一个是错误的。

So now I have the distasteful task of trying to convince a developer that they should really define their variables (in the .h file) in a manner that allows an automated method of creating all of the VB.NET function definitions easily. They will then smugly say, "read the ... documentation."

因此,现在我有一项令人厌恶的任务,即试图说服开发人员,他们应该以一种允许自动创建所有VB的方式来定义他们的变量(在.h文件中)。净函数定义。他们会沾沾自喜地说:“读……”文档”。

I have written an awk script that parses a .h file, and creates all of the Declare Function commands, but without an indicator as to which variables are R/O vs R/W, it only does half the job.

我已经编写了一个awk脚本,它解析了一个.h文件,并创建了所有的声明函数命令,但是没有一个指示变量是R/O vs R/W的指示器,它只做了一半的工作。

EDIT:

编辑:

At the encouragement of another user I am adding the following;

在另一个用户的鼓励下,我添加了以下内容;

Here is an example of a (IMO) poorly formed .h entry;

这里有一个(IMO)格式差的例子。

typedef int (EE_STDCALL *Do_SomethingPtr)( int smfID, const char* cursor_name, const char* sql );

The resultant VB from my script;

从我的脚本生成的VB;

    Declare Function Do_Something Lib "SomeOther.DLL" (ByRef smfID As Integer, ByVal cursor_name As String, ByVal sql As String) As Integer

Note the missing "const" on the first parameter. Without it, a program (or another developer) has no Idea the 1st parameter should be passed "ByVal." By adding the "const" it makes the .h file self documenting so that developers using other languages can easily write working code.

请注意第一个参数中缺少的“const”。没有它,程序(或其他开发人员)不知道第一个参数应该通过“ByVal”。通过添加“const”,它使.h文件自文档化,以便使用其他语言的开发人员可以轻松地编写工作代码。