
struct ListNode
{
};
bool check(ListNode* head)
{
}
答案:一种O(n)的办法就是(搞两个指针,一个每次递增一步,一个每次递增两步,如果有环的话两者必然重合,反之亦然):
bool check(ListNode* head)
{
}
2. C++的空类,默认产生哪些类成员函数?
答:
class Empty
{
public:
Empty();
Empty(const Empty& );
~Empty();
Empty& operator(const Empty& )
Empty& operator&();
const Empty* operator&() const;
}
3. const常量与define宏定义的区别
答:(1) 编译器处理方式不同。define宏是在预处理阶段展开,生命周期止于编译期。
只是一个常数、一个命令中的参数,没有实际的存在。
#define常量存在于程序的代码段。const常量是编译运行阶段使用,const常量存在于程序的数据段.
(2)类型和安全检查不同。define宏没有类型,不做任何类型检查,仅仅是展开。
const常量有具体的类型,在编译阶段会执行类型检查。
(3) 存储方式不同。define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。
const常量会在内存中分配(可以是堆中也可以是栈中)
4. 进程和线程的差别?
答:线程是指进程内的一个执行单元,也是进程内的可调度实体.区别:
(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行
(3)拥有资源:进程是拥有资源的一个单位,线程不拥有系统资源,但可以访问隶属于进程的资源.
(4)系统开销:创建撤消进程,系统都要为之分配和回收资源,系统的开销明显大于创建撤消线程
多进程与多线程,两者都可以提高程序的并发度,提高程序运行效率和响应时间。
5. 在C++程序中调用C编译后的函数,为什么要加extern C的声明?
答:因为C++支持函数重载,而C不支持函数重载,函数被C++编译后在库中的名字与C语言的不同。
假设某个函数的原型为:void foo(int x, int y);该函数被C编译器编译后在库中的名字为_foo,
而C++编译器则产生像_foo_int_int之类的名字。 C++提供extern C来解决名字匹配问题
6. 拷贝构造函数相关问题,深拷贝,浅拷贝,临时对象等
答:在C++中,三种对象需要拷贝的情况:一个对象以值传递的方式传入函数体,
一个对象以值传递的方式从函数返回,一个对象需要通过另外一个对象进行初始化。
执行先父类后子类的构造,对类中每一个数据成员递归地执行成员拷的动作.
深拷贝:如果一个类拥有资源,深拷贝意味着拷贝了资源和指针
浅拷贝:如果对象存在资源,而浅拷贝只是拷贝了指针,没有拷贝资源,
这样使得两个指针指向同一份资源,造成对同一份析构两次,程序崩溃。
临时对象:辅助一个表达式的计算 a + b + c ,或者间接构造的实参,函数返回非引用的时候,
都可能产生临时对象,临时对象生命周期,是单个语句,是右值。
临时对象的开销比局部对象小些。
7. 在main函数执行之前,还会执行什么代码和工作
答:运行全局构造器,全局对象的构造函数会在main函数之前执行
设置栈指针,初始化static静态和global全局变量,即数据段的内容
将未初始化部分的赋初值:数值型short,int,long等为0,bool为FALSE,指针为NULL等
将main函数的参数,argc,argv等传递给main函数
8. 静态成员函数能不能同时也是虚函数?
答案是不能。调用静态成员函数不要实例。但调用虚函数需要从一个实例中指向虚函数表的指针以得到函数的地址,因此调用虚函数需要一个实例。两者相互矛盾。
9. TCP/IP建立连接的过程
答:在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
第一次握手:建立连接时,客户端发送连接请求到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到客户端连接请求,向客户端发送允许连接应答,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的允许连接应答,向服务器发送确认,客户端和服务器进入通信状态,完成三次握手
10. 类成员函数的重载、覆盖和隐藏的区别
答案:
成员函数被重载的特征:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。
“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)
11. 给出算法思路,从10亿个浮点数当中,选出其中最大的10000个。
思路:先将数据进行分割成数据量小的一些文件,如1000000个数据为一个文件,然后将每个文件数据进行排序,用快速排序法排序,然后使用K路合并法将其合并到一个文件下,取出排序好的最大的10000个数据
12. 读程序
int func(int x)
{
}
int main()
{
printf("%d\\n", func(9999));
}
答案:8
思路:将x 转化为2 进制,看含有的1 的个数。
13. New delete 与malloc free 的联系与区别?
答案:都是在堆(heap)上进行动态的内存操作。用malloc 函数需要指定内存分配的字节数并
且不能初始化对象,new 会自动调用对象的构造函数。delete 会调用对象的destructor,而
free 不会调用对象的destructor.
14.下面的代码有什么问题?
void DoSomeThing(...)
{
char* p;
...
p = malloc(1024); // 分配1K 的空间
if (NULL == p)
return;
...
p = realloc(p, 2048); // 重新分配到2K
if (NULL == p)
return;
...
}
答:
p = malloc(1024); 应该写成: p = (char *) malloc(1024);
没有释放p 的空间,造成内存泄漏。
15.执行结果
void main()
{// test1
答:6:4:1:4
16. main 主函数执行完毕后,是否可能会再执行一段代码,给出说明?
答:可以用_onexit 注册一个函数,它会在main 之后执行int fn1(void), fn2(void)
int fn1(void)
{
}
int fn2(void)
{
}
int main()
{
printf( "This is executed first.\\n" );
}
17. i最后等于多少?
int i = 1;
int j = i++;
if((i>j++) && (i++ == j)) i+=j;
答:i = 5
