在c++中,const关键词出现在很多地方,有诸多的用途,也有很多的限制。
这里简单的列举一下const声明和定义的注意事项:(const对象定义时必须初始化,下面的例子只是说明一下const位置的含义)
-
const出现在声明或者定义变量的类型的前面的时候,const修饰的是变量本身
如:const char *value; //指针a指向const char类型,是指指针所指的变量不能改变,而指针本身的值可以改变
-
其它情况的const修饰其左边的符号:
- char *const value;//表明value指针是常指针,不可以改变它的指向,但是它所指向的对象可以改变
- char const* value;//表明value指针所指的对象是const char型,指针的指向可以改变(同const char* value;)
- const char* const value;//第一个const表明value所指的对象是const char型,第二个const表明指针本身是常指针,因此这里的value是指向常对象的常指针
- 上面的例子等价于:char const* const value;第一个const修饰char(表明指针所指的对象是const char型)第二个const表明value是指向const char的constant指针
-
可以用typedef来便于理解(从右边往左边读):
例如:typedef char* a;
a const b;
b是const a类型,而a是指向char的指针,因此b是指向char的const 指针
- 综上呢,如果不能熟练的掌握const的位置和用法,将const修饰符放在类型的后面总是更容易理解的且不易出错的。
- 这个问题呢,是来自于C++primer 第4版的一个实例(是在看知乎的时候发现书中的这个实例被看的时候忽略了)
下面是这个实例(是讲函数模板和其特化)
1. template<class T> 2. int compare(const T &a1, const T &a2) 3. { 4. std::cout << "not specialization " ; 5. 6. if (a1 < a2) 7. return -1; 8. else if (a1 > a2) 9. return 1; 10. return 0; 11.} 12. 13.template<> 14.int compare<const char*>( const char const* &a1, const char const* &a2) 15.{ 16. std::cout << "specialization " ; 17. return strcmp(a1, a2); }
这个模板很简单,就是比较两个形参的大小,然后返回比较结果。
然而如果将const char *的对象(如:"gaoduan")传递给该模板,则比较两个指针的地址,而不是我们所想要的结果,因此要对此模板进行特化,特化的方式很简单,以template<>开头,然后将模板中的类型参数T用具体的类型替代即可。(需要注意,特化的版本只会在实参精确匹配的时候调用,如此例中,若实参为char *或者char *const的时候都会调用原来的泛型版本,只有const char *的参数(注意,字面值常量可以和const型参数匹配)会调用特化类型的模板)
这里我们将const char *类型实例化,注意到函数形参是char const* const &类型
这里应该这样理解:
- 在原模板中,类型形参为T,函数形参为指向T的const引用
- 特化模板中,类型形参为const char *,因此函数形参应为指向const char *类型的const引用
因此,形参中应该有两个const,一个修饰引用,一个修饰char,
因此,应该写作const char const* &(第一个const修饰最后的变量,即修饰引用,第二个const修饰char)
或者,可以写作char const* const & 可以解读为:
typedef char const *A; A const&B;(A为指向const char的指针,B为指向A的常引用),因此也正确;