刷大疆的面试题目看到了这个问题,学习并记录一下……
一、const在函数前
const在函数前,就是我们比较容易理解的,返回一个const类型的变量。这个变量不可修改。
测试代码如下。
#include<iostream>
using namespace std;
const int* func(int a,int *b)
{
b=&a;
return b;
}
int main()
{
int *c;
const int *d=func(2,c);//这一句编译没报错
int *e=func(2,c);//这一句编译报错,不能从const int*类型转换为int*类型
return 0;
}
说点题外话,上述代码,编译器没有发出警告,但其实这样写是有问题的。
func函数中,返回的是b的值,也就是返回了a的地址,而a是func函数申请的一个局部变量,存储在栈中,当函数执行结束后,这些局部变量都是要释放掉的,所以返回了a的地址其实没什么用。
举个例子,如果你在函数中计算得到一个值,存储在一个局部变量中,最后返回这个局部变量的地址,在main函数中得到这个地址,然后再拿出来一看,可能已经不是当初计算出来的值了。
测试代码如下。
#include<iostream>
using namespace std;
int * func(int a)
{
int b=a+1;
return &b;
}
int main()
{
int *c;
c=func(2);
int *d;
d=func(12);
cout<<*c<<endl;//输出13
return 0;
}
上述代码之所以输出13,是因为第一次调用了func,形参是2,最后返回了地址,存储在c中,释放了栈中的局部变量。接着第二次调用func,形参是12,最后再返回了地址,存储在d中,这个时候c跟d其实对应的是栈中的同一个内存单元。所以输出*c会得到13。
如果不要第二次调用形参是12的func,那么输出*c还是3。值是相同的,但是十分不建议这样子实现一个函数,在大型代码构建中十分容易出错。
除此之外,笔者还发现了一个问题,如果返回的是const int类型的变量,而不是const int*类型的变量,那么在main函数中不加const,似乎也是可以通过编译,并且成功修改元素值的。
测试代码如下。
#include<iostream>
using namespace std;
const int func(int a)
{
const int b=a;
return b;
}
int main()
{
int c=func(2);
c++;
cout<<c<<endl;
return 0;
}
关于这一点,笔者还没有想明白为什么。
二、const在函数后
const在函数后,比如在类中的某个成员函数后,表示的是这个函数不能修改类成员的值。
测试代码如下。
#include<iostream>
using namespace std;
class person
{
public:
void func() const
{
cout<<var1<<endl;
var1=2;//报错,类中的const函数不可以修改类成员变量的值
func1();//通过编译,const函数可以调用const函数
func2();//报错,const函数不可以调用非const函数,因为不能确保调用的函数不会改变类成员变量的值
}
void func1() const
{
cout<<var1<<endl;
var1=3;//报错,类中的const函数不可以修改类成员的变量值
}
void func2()
{
cout<<var1<<endl;
var1=4;
}
private:
int var1=1;
};
类中如果有static成员函数,那么这个成员函数不能在后面加上const。
原因是static成员函数没有this指针这个隐藏参数,而普通的类成员函数有this指针。
可能是当添加上const声明后,指向这个函数的指针变成一个常量指针,指向常量的指针,所以这个函数不能修改类成员变量的值。但是static没有this指针,无法变成一个常量指针。
笔者不确保上述理由一定十分正确,这是一个比较简单的理解。如果有错,还请指出~