关于C++的面试题

一、谈一谈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++编译器是如此好骗,今天就到这里。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-10 19:59:52

关于C++的面试题的相关文章

【转】嵌入式软件工程师经典笔试题

嵌入式软件工程师经典笔试题 > 预处理器(Preprocessor) 1. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 我在这想看到几件事情: 1). #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等) 2). 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中 有多少秒而不是计算出实际的值,是更清晰而没有代价的. 3).

10个常见的Node.js面试题

如果你希望找一份有关Node.js的工作,但又不知道从哪里入手评测自己对Node.js的掌握程度. 本文就为你罗列了10个常见的Node.js面试题,分别考察了Node.js编程相关的几个主要方面. 在进入正文之前,需要提前声明两点: 这些问题只是Node.js知识体系的一个局部,并不能完全考察被面试者的实际开发能力. 对现实世界开发中遇到的问题,需要的是随机应变与团队合作,所以你可以尝试结对编程. Node.js面试题列表 什么是错误优先的回调函数? 如何避免回调地狱? 如何用Node来监听8

.NET教程:.NET 面试题之IEnumerable

.NET教程,今天给大家介绍的是:.NET 面试题之IEnumerable ,这是在面试的时候可能会碰到的一道题目,这道题的注解分为了两个部分,这一篇是第一部分! 什么是IEnumerable? IEnumerable及IEnumerable的泛型版本IEnumerable是一个接口,它只含有一个方法GetEnumerator.Enumerable这个静态类型含有很多扩展方法,其扩展的目标是IEnumerable. 实现了这个接口的类可以使用Foreach关键字进行迭代(迭代的意思是对于一个集合

java 19 - 9 finally有关的面试题

1 /* 2 * 面试题: 3 * 1:final,finally和finalize的区别 4 * final:最终的意思,可以修饰类,成员变量,成员方法 5 * 修饰类,类不能被继承 6 * 修饰变量,变量是常量 7 * 修饰方法,方法不能被重写 8 * finally:是异常处理的一部分,用于释放资源. 9 * 一般来说,代码肯定会执行,特殊情况:在执行到finally之前jvm退出了 10 * finalize:是Object类的一个方法,用于垃圾回收 11 * 12 * 2:如果catc

java面试题大全

java面试笔试题大汇总     第一,谈谈final, finally, finalize的区别. 最常被问到. 第二,Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)? 第三,Static Nested Class 和 Inner Class的不同,说得越多越好(面试题有的很笼统). 第四,&和&&的区别. 这个问得很少. 第五,HashMap和Hashtable的区

【面试】iOS 开发面试题(二)

1. 我们说的oc是动态运行时语言是什么意思? 答案:多态. 主要是将数据类型的确定由编译时,推迟到了运行时. 这个问题其实浅涉及到两个概念,运行时和多态. 简单来说,运行时机制使我们直到运行时才去决定一个对象的类别,以及调用该类别对象指定方法. 多态:不同对象以自己的方式响应相同的消息的能力叫做多态.意思就是假设生物类(life)都用有一个相同的方法-eat; 那人类属于生物,猪也属于生物,都继承了life后,实现各自的eat,但是调用是我们只需调用各自的eat方法. 也就是不同的对象以自己的

JAVA常见面试题及解答-java开发

JAVA常见面试题及解答 Java的垃圾回收总结  浅谈Java中的内部类 1)transient和volatile是java关键字吗? 如果用transient声明一个实例变量,当对象存储时,它的值不需要维持.例如: class T { transient int a;  //不需要维持 int b;  //需要维持 } 这里,如果T类的一个对象写入一个持久的存储区域,a的内容不被保存,但b的将被保存. volatile修饰符告诉编译器被volatile修饰的变量可以被程序的其他部分改变.在多

链表面试题Java实现【重要】

本文包含以下内容: 1.单链表的创建和遍历 2.求单链表中节点的个数 3.查找单链表中的倒数第k个结点(剑指offer,题15) 4.查找单链表中的中间结点 5.合并两个有序的单链表,合并之后的链表依然有序[出现频率高](剑指offer,题17) 6.单链表的反转[出现频率最高](剑指offer,题16) 7.从尾到头打印单链表(剑指offer,题5) 8.判断单链表是否有环 9.取出有环链表中,环的长度 10.单链表中,取出环的起始点(剑指offer,题56) 11.判断两个单链表相交的第一个

Android-异步任务介绍及面试题

Android-异步任务 一 什么是AsyncTask Android为了减低异步操作的开发难度,结合Handle和线程池,提供了AsyncTask.AsyncTask就是一个封装过的后台任务类, 顾名思义就是异步任务,他具有可以在后台执行耗时操作,同时可以将 执行的进度与UI进行同步的优点 因为Handle实际上就是两个线程之间的桥梁,但是数据的传递是单向的 Handle机制如下图: 而AsyncTask机制如下: 二 如何使用AsyncTask AsyncTask定义三种泛型类型Params

Java面试题全集(中)

这部分主要是与Java Web和Web Service相关的面试题. 96.阐述Servlet和CGI的区别? 答:Servlet与CGI的区别在于Servlet处于服务器进程中,它通过多线程方式运行其service()方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于Servlet. 补充:Sun Microsystems公司在1996年发布Servlet技术就是为了和CGI进行竞争,Servlet是一个特殊的Java程