为什么将函数声明为const很有用,即使您只能读取变量而无法写入(类变量)?
const_cast
修改对象,基本上只有在 const_cast
的用户最初添加了 const
修饰符到原本不是 const
的指针或引用时才合法。 - Ben Voigt如果你将你的类的实例作为const指针或const引用传递给其他对象,则只能调用该类的const方法(如果有的话)。
显然,如果您从不关注类型的const正确性,则可以忽略此问题。
我认为这也可能在某些情况下帮助编译器优化代码,尽管我对此表示怀疑,即使它确实有所帮助,在大多数情况下,允许这种微小的改进来决定你如何编写代码将是一种过早优化的情况。
一个原因是const
是一种病毒。这意味着如果代码的一部分是const-correct,那么其他代码就无法与该部分进行交互。
如果忽略const-correctness,你的类很难与其他库(以标准库开头)配合工作。
例如:
#include <vector>
#include <algorithm>
struct X
{
int n;
bool operator< (X b)
{
return n < b.n;
}
};
int main()
{
std::vector<X> vec;
std::sort(vec.begin(), vec.end());
}
使用codepad.org
In function 'const _Tp& std::__median(const _Tp&, const _Tp&, const _Tp&) [with _Tp = X]':
/usr/local/lib/gcc/i686-pc-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2642: instantiated from 'void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size) [with _RandomAccessIterator = __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<X*, __gnu_norm::vector<X, std::allocator<X> > >, __gnu_debug_def::vector<X, std::allocator<X> > >, _Size = int]'
/usr/local/lib/gcc/i686-pc-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2713: instantiated from 'void std::sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<X*, __gnu_norm::vector<X, std::allocator<X> > >, __gnu_debug_def::vector<X, std::allocator<X> > >]'
t.cpp:17: instantiated from here
Line 90: error: no match for 'operator<' in '__a < __b'
一个符合stdlib的比较运算符必须保证参数不被修改。如果在比较过程中对象实际上发生了变化,那么对它们进行排序的尝试将是徒劳的。
另一个例子:传递大对象的常规方式是通过const引用传递参数。但现在你必须通过可修改的引用来传递参数。现在您无法将任何类型的临时对象传递给函数。
你在代码中表达调用方和被调用方之间的契约,而不是文档,越多,编译器就能更好地帮助你遵守这个契约(从两端)。隐式 this
指针的 const-ness 以及所有其他参数引用的 const-ness 都是其中重要的部分。(当然,按值传递的顶层 constness 不是契约的一部分)