const在函数前和在函数后

Posted by chenjx85 on May 13, 2019

刷大疆的面试题目看到了这个问题,学习并记录一下……

一、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指针,无法变成一个常量指针。

笔者不确保上述理由一定十分正确,这是一个比较简单的理解。如果有错,还请指出~