你用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)

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


当前回答

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

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

其他回答

在你提到的情况下,它不会影响API的调用者,这就是为什么它不常做(并且在头文件中也没有必要)。它只影响函数的实现。

这并不是一件特别糟糕的事情,但考虑到它不会影响您的API,它的好处并不是那么大,而且它增加了类型,所以通常不这样做。

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

当然,程序通过在出错的行上生成一个异常错误来告诉您,但是随后您需要猜测2-10个参数中哪一个是错误的。

所以现在我有一个令人讨厌的任务,试图说服开发人员,他们应该真正定义他们的变量(在.h文件中),以一种允许自动创建所有VB的方法。NET函数定义容易。然后他们会自鸣得意地说:“读……文档”。

我写了一个awk脚本,它解析一个.h文件,并创建所有的Declare Function命令,但没有指示哪个变量是R/O vs R/W,它只完成了一半的工作。

编辑:

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

下面是一个(IMO)格式不佳的.h条目的例子;

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

从我的脚本的结果VB;

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

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

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

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

当我以编写c++为生时,我尽可能地压缩了所有东西。使用const是一种帮助编译器帮助你的好方法。例如,const你的方法返回值可以避免你输入错误,例如:

foo() = 42

你的意思是:

foo() == 42

如果foo()被定义为返回一个非const引用:

int& foo() { /* ... */ }

编译器很乐意让您为函数调用返回的匿名临时对象赋值。使其为const:

const int& foo() { /* ... */ }

消除了这种可能性。

当参数按值传递时,Const是没有意义的,因为你不会修改调用者的对象。

通过引用传递时应优先使用Const,除非函数的目的是修改传递的值。

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

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

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

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

如果函数不是const,则会导致编译器警告。