我们知道,const存在的意义之一,就是用来对指针或引用类型的形参进行限定,从而达到防止修改实参的作用(因为只有指针和引用类型非按值传递)。使用const指针或引用形参的理由有如下几条:
- 1.const形参可以接受非const实参,而非const形参只能接受非const实参;
如:
void sum(const int*,int*);
int main()
{
int i = 1,j = 3;
sum(&i,&j);//OK,第一个参数const int*可以接受int*类型数据
return 0;
}
void sum(const int* a,int* b)
{
cout << "sum: " << (*a + *b) << endl;
}
- 2.使用const形参可以避免无意识的修改实参,如上例中形参a为
const int*
类型,不能修改a的值; - 3.如果形参为引用类型,使用const形参可以在必要时生成临时变量,包括以下两种场景:
- 3.1.实参类型正确,但非左值;
- 3.2.实参类型不正确,但可以转化为正确的类型;
如:
void sum(const int& a,int& b);
int main()
{
double a = 3.45;
int b = 4;
sum(a,b); //OK,实参类型不正确(double),但由于const的存在,会生成一个临时变量,然后让a指向这个变量
//sum(b,a);//BAD,int&形参不会接受double实参
sum(5,b);//OK,5非左值,但const int&可以接受
//sum(b,5);//BAD,5非左值,int&不会接受
return 0;
}
因此,const 修饰的指针类型可以接受它的非const形式,如const int*
类型形参可以接受int*
类型实参,const char*
可以接受char*
类型实参,const float*
类型形参可以接受float*
类型实参,…
那么,const char **
类型形参可不可以接受char**
类型实参呢?
我们先试一下:
#include <iostream>
using namespace std;
void print(const char** pch);
int main()
{
char* name = new char[20];
char ch;
cout << "please enter a name:" << endl;
cin.getline(name,20);
print(&name);
return 0;
}
void print(const char** pch)
{
cout << "pch:" << *pch << endl;
}
编译时,发现出错:
$ g++ test_const.cpp -o tc
test_const.cpp: In function ‘int main()’:
test_const.cpp:17:15: error: invalid conversion from ‘char**’ to ‘const char**’ [-fpermissive]
print(&name);
^~~~~
test_const.cpp:7:6: note: initializing argument 1 of ‘void print(const char**)’
void print(const char** pch);
^~~~~
很显然,const char**
类型形参是不接受char**
类型实参的,这是为什么呢?
在C标准中规定,对于赋值操作,必须满足如下的条件:
- 1.两操作数都是指向有限定符或无限定符的相容类型的指针;
- 2.左边指针必须具有右边指针所指向类型的全部限定符;
所以,对于const char*
和char*
来说:
const char* cch;
char* ch;
cch = ch;
左操作数是一个指向有const修饰的char类型的指针;
右操作数是一个指向char类型的指针;
char 和char 是相容的(同一类型),且左操作数具有右操作数的全部限定符,还多了一个const。因此,是允许这样操作的。
对于const char**
和char**
来说:
const char** cch;
char** ch;
cch = ch;
左操作数是一个指向有const修饰的char的指针的指针;
右操作数是一个指向没有const修饰的char的指针的指针;
首先,两操作数都是没有限定符的指针类型,分别指向const char *
和char *
,因此,它们的类型不同,因此,不满足第一个条件,从而不能完成赋值。
同样地,我们也可以知道,const float**
不接受float**
,const int**
不接受int *
…
参考资料:《C专家编程》