一、谈一谈static
这个问题不算太难,但是要完整的把static的作用说完还是有一定难度的。
A、首先解释static在C语言中的作用,这些作用在C++中被完全继承了。
(1)所有使用static修饰过的变量如果未被显式初始化,则被存储在bss段,BSS段在二进制程序中是没有实际存储的,只有在程序运行时才会为BSS段分配内存同时进行默认初始化 ,在C语言中也就是赋值为0 。如果显示初始化了,那么就存储在data段。而不管是bss段还是data段,其生命周期都是全局的,所谓全局就是main函数执行之前他们已被初始化,在main函数执行结束,他们的内存才被清理。
(2)对与定义在函数内部的static变量,他们的访问权限仍然只在本函数内部,由于生命周期是全局的,所以每一次函数调用,他们的值都保留上一次调用的结果,如果第一次调用,则未初始化的值。同样,由于static变量被每次函数调用所共享 , 因此如果一个定义了static变量的函数被多个线程调用了,就会出现不一致状态。这种函数在多线程中被称之为不可重入函数,如果没有保护措施,是不能直接在多线程中调用的。
(3)对于函数和全局变量,static声明是得该函数或者变量只能被本文件访问,不能被其他文件访问,C语言一般使用这个特性来实现信息的隐藏。
B、再说C++中static除C语言之外的特性。
(1)第一点其实不算是特性,指的是static的非pure_data对象,这种对象的生命周期任然是全局的,也就是说他们的构造函数在main函数之前执行,析构函数在main函数之后执行。
(2)定义在类中的static成员对象和成员函数是被整个类共享的,而不是特定对象的。
二、关于const的实现
这是在网上看到的一个腾讯面试题,但是非常让人满意的答案似乎不是很容易找到。那么同样先追溯到c语言中的const(好像只有c99新标准才支持const,姑且就用它先来解释),c语言中没有类和对象以及引用一说,因此const只用来修饰变量(实际上修饰后变成了常量)。那么如何保证用const修饰过的值不会被修改呢,一种是编译器来检查,如果被修改了就在编译时报错。这种方式保证不被修改实际上是不可靠的,因为我们可以通过一系列奇技淫巧来绕过编译器的检查,这时候只要编译时不报错,运行时及时把const修饰的值修改了,也不会让程序崩溃。另一种方法是除了编译器的编译时检查外,引入操作系统的运行时保护,也就是把使用const修饰了的值定义在代码区,这样即使采用奇技淫巧骗过了编译器,运行的时候也会引起段错误而导致程序死翘翘,但是这样我们也会注意到一个问题,要保存在代码区必须是编译时已经确定的值,如果我用一个只有运行时才知道的值来初始化const修饰的值,(比如函数调用中用到了一个const *pv参数),这个总不能也放到代码区吧。那么C/C++是如何实现const修饰的值不被修改呢?我认为两者都采用了,如果是c++11新标准,那么这个问题就变得很明确,constexpr采用了编译器检查 + 操作系统的保证,也就是定义在代码区。而const只采用编译器检查。在c++11新标准之前这个道理任然有用,能在编译器确定其值的,就采用双重保护,否则只采用编译器检查来保证。对于const修饰的函数来说,只能采用编译器检查来保护,操作系统是无能为力的。因此,我们可以看出,像所谓const修饰的成员函数内不能改变对象的状态这类约束,只是编译器的检查使得我们直接改变对象的状态不能通过编译,我们完全可以想办法骗过编译器,比如这样:
class Hehe
{
public:
Hehe(int x = 0) : x_(x){}
void hfunc(Hehe *hp)const
{
hp->x_ = 100;
}
int getx()const
{
return x_;
}
private:
int x_;
};
int main(int argc , char *argv[])
{
Hehe h;
h.hfunc(&h);
cout<<h.getx()<<endl;
}
程序执行结果:100
呵呵,看来C++编译器是如此好骗,今天就到这里。
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/yuanliang01xiaolang/article/details/47981837