突破编程_C++_面试( static 与 const )

本文详细解释了C++中static关键字在全局函数、局部变量、类成员上的作用,以及const关键字用于常量定义、函数参数、指针和类中的意义,比较了const与define的区别,强调了const在编程中的优点。
摘要由CSDN通过智能技术生成

1 面试题1:static的用法

static 关键字可用于修饰全局函数和全局变量、函数的局部变量、类数据成员和类函数。
(1)修饰全局函数和全局变量:只能在本代码文件中使用。
(2)修饰函数的局部变量:有默认值0。始终驻留在全局数据区,直到程序运行结束。但其作用域仍为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。虽然静态局部变量在函数调用结束后仍然存在,但其他函数是不能引用它的。
(3)修饰类数据成员和类函数:不依赖于类对象的存在而存在。 static 类函数不可以使用 this 指针,同时 static 类函数也不能声明为虚函数

1.1 作用1:保持变量内容的持久

定义为 static 的变量会在程序刚开始运行时就完成初始化,这也是唯一的一次初始化。定义为 static 的变量在程序的运行过程中存储在静态数据区( C++ 的内存包括栈区、堆区、全局区(静态区)、BSS段、文字常量区以及程序代码区)。特别是对于静态局部变量而言,该变量也是始终驻留在全局数据区,直到程序运行结束。

static int s_val = 0;			// 静态全局变量 

int main()
{
	static int val2 = 0;		// 静态局部变量 
	
	return 0;
}

上面代码中的 s_valval2 的声明周期均是整个程序运行过程。

1.2 作用2:隐藏

当同时编译多个文件时,被 static 关键字修饰全局函数和全局变量只能在本代码文件中使用,而所有未加 static 前缀的全局变量和函数都具有全局可见性。
该功能在 C 代码中更为常见,用于实现类似 C++ 中的私有成员变量以及私有成员函数的特性。

1.3 作用3:默认初始化为0

C++ 的内存分布中的两个区域:全局区(静态区)与 BSS 段。这两个区域所有的字节默认值都是0x00。
(1)全局区(静态区): 全局变量和静态变量的存储是放在一块的。初始化的全局变量和静态变量在一块区域,未初始化的全局变量和静态变量又放在相邻的另一块区域中。程序结束后由系统释放。
(2)BSS段 :通常是指用来存放程序中未初始化的全局变量、静态变量(全局变量未初始化时默认为 0 )的一块内存区域。

1.4 作用4: static 修饰类数据成员和类函数

(1)static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
(2)static 成员函数属于整个类所拥有,这个函数不接收 this 指针,并且只能访问类的 static 成员变量。
(3)static 成员函数不能被 virtual 修饰(即不能为虚函数)。

2 面试题2:const 关键字的作用

使用 const 关键字可以创建命名常量,即具有特定名称的常量变量。const 修饰符用于表示变量的值是不可修改的。例如:

const int val1=1;   

2.1 const 关键字修饰函数入参

设计函数参数的有一个原则是:能用 const 的就用 const(方便调用) 。比如创建一个用于打印字符串的函数。从这个需求来看,这个函数有一个字符串的入参,在其函数体中,只要读入这个字符串入参即可,无需对其修改。如果设计一个按值传递的函数,如下:

void printStr(string& str)		//采用引用的原因是避免值传递带来的拷贝过程,从而造成性能损失
{
	printf("%s\n",str.c_str());
}  

这样就会带来另外两个问题,第一:该函数只需要读入字符串的入参,并不用对其做修改,而按引用的传递,赋予了这个函数不应该有的权限。第二:不方便调用,比如有如下调用方式:

void printStr(string& str)
{
	printf("%s\n",str.c_str());
}

int main()
{
	printStr("hello");			//错误:由于字符串 "hello" 是 const 类型,所以这里编译会报错。
	
	return 0;
}

因此,最合理的设计就是使用 const 关键字:

void printStr(const string& str)
{
	printf("%s\n", str.c_str());
}

2.2 const 关键字修饰指针

对指针来说,可以指定指针本身为 const ,也可以指定指针所指的数据为 const ,或二者同时指定为 const 。两者区别如下:
如果 const 位于*的左侧,则 const 就是用来修饰指针所指向的变量,即指针指向为常量。例如:

int a=1;
const int * ptr = &a;		//等同于 int const * ptr = &a;
*ptr = 2;					//错误:不能通过指针来修改变量的值

如果 const 位于*的右侧, const 就是修饰指针本身,即指针本身是常量。例如:

int a = 1;
int b = 2;
int * const ptr = &a;
ptr = &b;					//错误:不能修改指针的指向

2.3 const 关键字在类中的作用

使用 const 关键字修饰的类的成员函数,表明其是一个常函数,可以访问非 const 数据成员,也可以访问 const 数据成员。但是 const 成员函数不能修改类的成员变量,另外类的常对象只能访问类的常成员函数。如下为样例代码:

#include <iostream>
using namespace std;

class Student
{
public:
	Student() {}
	~Student() {}

public:
	void sayHello() const
	{
		m_name = "zhangsan";				//错误: 不能修改类的成员变量
		printf("%s\n", m_name.c_str());
	}

	string getName()
	{
		return m_name;
	}

private:
	string m_name;
};

int main()
{
	Student st;
	st.sayHello();

	const Student st2;
	string name = st2.getName();			//错误: const 对象不能调用非 const 成员函数

	return 0;
}

2.4 const 与 define 定义常量的区别

(1)处理阶段
const 常量是一个Run-Time的概念,他在程序中确确实实的存在可以被调用、传递。
define 常量是预处理器预处理阶段完成的,它的生命周期止于编译期:在实际程序中他只是一个常数、一个命令中的参数,没有实际的存在。
(2)定义不同
define 是宏定义,它最大的特点就是语义替换,它定义的常量值没有类型限定,不做运算,也不做类型检查,在宏出现的地方直接展开。例如:

#define VAL 1+1 //我们预想的 VAL 值是 2 ,我们这样使用 VAL 
double a = VAL/2; //我们预想的a的值是1,可实际上 VAL 的值是 2
//实际上就是 a = 1+1/1 = 2

const 是关键字,其实就是一个只读变量,不能更改,它会在编译时检查数据类型。
(3)存储方式
const 常量存在于程序的数据段。
define 常量存在于程序的代码段。
const 定义的只读变量在程序运行过程中只有一份拷贝(因为它是全局的只读变量,存放在静态区),而#define定义的宏常量在内存中有若干个拷贝。
就空间效率而言:const 优于 define。
总结上述区别:一般推荐使用const关键字定义常量,因为它具有类型限制,更安全、更可读、更易于维护。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值