最近的面试笔试题总结

1.

char *a = new char[5];

a = "12345";

能运行,但可能出错,存在地址越界

 

2.

公有继承下,基类数据成员在派生类中的访问权限:

基类的公有和保护成员的访问属性在派生类中不变,而基类的私有成员不可直接访问。

 

3.

new申请某一个类的动态对象数组时,该类中必须能够匹配到 无参数的 构造函数。

 

4.

在C++中,函数的参数有两种传递方式,它们是值传递和 地址 传递。

 

5. 一道面试题C++怎么给类的私有成员变量赋值

classA{

   private:int i;

   public:int j;

}

voidmain(){

   A a;

   a.j=1;

}

怎么给i赋值

void main(){
   A a;
   a.j=1;
   //用指针实现://可以达到
   int *pI=(int *) (&a);
   *pI=1234;
}
 

题目没有说字节对齐方式?我没测试,你自己整一下。

 

6.工作流的程序

http://www.cnblogs.com/foundation/articles/852822.html

 

7.istrstream 定义于#include <strstream>

istrstream流以空格为分割符

 

8.linux命令

pws   显示当前目录

 

9、 当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型

10、再调用main函数前执行一些操作,如果实现?

class A
{A(){printf("before main!\n");}}
A a;
这样就可以调用了。

 

编译器定地

上面这一堆人在回答什么?没有一个回答在点上。
请问"规定"从main调用,这和C语言有鸟关系?
windows的PE要求一个代码入口点,你完全可以把main改成你想要的任何名字。

 

忽悠一下编译器就可以调用了,如下改写代码:
#include <stdio.h>

int nRet = printf("before main!\n");

int main()
{
  return 0;
}

程序StartCode为了初始化全局变量nRet的值,只能调用printf函数,这样就可以了。

11、多态笔试面试题

1C++中多态是怎么实现的?

1)在基类含有虚函数的情况下,编译器会为继承体系的每个类在编译期创建一个虚函数表(vtable),虚表中的每一项存储了这个类中虚函数地址,在派生类中,如果没有重写虚函数,则使用基类的虚函数实现。

2)类的对象包含一个虚指针(vptr),在运行时的构造函数中初始化,指向所属类型的虚表。

3)调用的时候用基类的指针指向派生类的对象,从而实现了动态联编。

2、构造函数为什么不能是虚函数

虚函数只产生一次函数调用;创建派生类的时候,构造函数会先执行基类的构造函数,再执行派生类的构造函数,即产生了多次调用,所以构造函数不能是虚函数。

 

12、内存碎片

使用应用层Cache。应用程序启动过程把所有需要的内存一次性申请出来。自己管理内存,不要频繁申请、释放内存。

如果保存的内存是不同的结构体,那么就使用不同的链,一次性申请10000个同样的结构体,挂链,申请的时候直接摘链,用完了再插链。

 

13、strcpy的实现

char * strcpy( char *strDest,const char *strSrc )

{

  assert( (strDest != NULL)&&(strSrc != NULL) );

  char *address = strDest;

  while( (*strDest++ = *strSrc++) != ‘\0’ );

  return address;

}

 

 

14、单链表中判断是否存在环

bool check(const node* head)

{

    if(head==NULL)return false;

    node*low=head, *fast=head->next;

    while(fast!=NULL&& fast->next!=NULL)

     {

        low=low->next;

        fast=fast->next->next;

        if(low==fast) return true;

    }

     returnfalse;

}

 

 

15、一个字符串,循环右移2位

1)技巧  split and reverse

2) 两个数组

 

16、十进制转换为二进制、十六进制,并输出

 

 

17、智力题

两个盲人,8双袜子

:一双袜子,每人分一只

一个金块,一个工人工作7天

:见前面讲的工作流

对一批编号为1~100,全部开关朝上(开)的灯进行以下*作:凡是1的倍数反方向拨一次开关;2的倍数反方向又拨一次开关;3的倍数反方向又拨一次开关……问:最后为关熄状态的灯的编号。

:因子个数为奇数的即是!

1/4/8/16/25/36/49/64/81/100

两个桶,一个3升,一个5升

3*3(9)个点,用四条直线连接所有的点

两根香,每根烧完要一个小时,香不均匀

:先一根点两头,另一根点一头,等第一根烧完,第二根再点另一头

18、c++中const作用

1)
 
可以定义const常量

2)
 
便于进行类型检查 

3)
 
可以保护被修饰的东西
 
防止意外的修改,增强程序的健壮性。

 void f(const int i) { i=10;//error! }
      //
如果在函数体内修改了i,编译器就会报错

4)
 
可以很方便地进行参数的调整和修改
 
同宏定义一样,可以做到不变则已,一变都变

5)
 
在类中,为函数重载提供了一个参考

6)
 
可以节省空间,避免不必要的内存分配
 const
定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝

19、什么是多态
在面向对象语言中,接口的多种不同的实现方式即为多态;
简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

多态是一种机制、一种能力,而非某个关键字。它在类的继承中得以实现,在类的方法调用中得以体现。

多态的作用:

那么,多态的作用是什么呢?我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用(方法重用)!

20、C++四种强制转换

static_cast

const_cast

dynamic_cast

reinterpret_cast

 

21、calloc、malloc、realloc、sbrk、alloc、free等的作用及区别

 

22、编写类String 的构造函数、析构函数和赋值函数(25 分)

已知类String 的原型为:

class String

{

    public:

    String(constchar *str = NULL); // 普通构造函数

    String(constString &other); // 拷贝构造函数

     ~String(void); // 析构函数

     String& operate =(const String &other); // 赋值函数

    private:

     char*m_data; // 用于保存字符串

};

请编写String 的上述4 个函数。

标准答案:

// String 的析构函数

String::~String(void) // 3 分

{

     delete[] m_data;

     // 由于m_data 是内部数据类型,也可以写成 delete m_data;

}

// String 的普通构造函数

String::String(const char *str)// 6 分

     {

        if(str==NULL)

        {

            m_data = new char[1]; // 若能加 NULL 判断则更好

            *m_data = ‘\0’;

        }

        else

        {

        int length = strlen(str);

        m_data = new char[length+1]; // 若能加 NULL 判断则更好

        strcpy(m_data, str);

     }

}

// 拷贝构造函数

String::String(const String&other) // 3 分

{

    intlength = strlen(other.m_data);

     m_data= new char[length+1]; // 若能加 NULL 判断则更好

    strcpy(m_data,other.m_data);

}

// 赋值函数

String & String::operate=(const String &other) // 13 分

{

     // (1) 检查自赋值 // 4 分

     if(this== &other)

    return*this;

    // (2) 释放原有的内存资源 // 3 分

    delete[] m_data;

     // (3)分配新的内存资源,并复制内容 // 3 分

    intlength = strlen(other.m_data);

    m_data =new char[length+1]; // 若能加 NULL 判断则更好

    strcpy(m_data, other.m_data);

     // (4)返回本对象的引用 // 3 分

     return*this;

}

23、 Which is the correct output for thefollowing code

double dArray[2] = {4, 8}, *p,*q;

p = &dArray[0];

q = p + 1;

cout << q – p << endl;

cout << (int)q - (int)p<< endl;

a) 1 and 8

b) 8 and 4

c) 4 and 8

d) 8 and 1

选A;

第一个是指针加减,按照的是指向地址类型的加减,只跟类型位置有关,q和p指向的数据类型以实际数据类型来算差一个位置,因此是1。而第二个加减是实际指针值得加减,在内存中一个double类型占据8个字节,因此是8

24、全局变量和局部变量有什么区别?是怎么实现的?操作系统和编译器是怎么知道的?

全局变量的生命周期是整个程序运行的时间,而局部变量的生命周期则是局部函数或过程调用的时间段。其实现是由编译器在编译时采用不同内存分配方法。全局变量在main函数调用后,就开始分配,如果是静态变量则是在main函数前就已经初始化了。而局部变量则是在用户栈中动态分配的(还是建议看编译原理中的活动记录这一块)

25、winsock建立连接的主要实现步骤?

答:

TCP:服务器端:1.socket()建立套接字,2将套接字绑定到本地地址和端口上,绑定(bind)3.将套接字设为监听模式,准备接收客户端,监听(listen);4.等待客户端请求到来,请求到来后,连接请求,并返回一个新的对应此连接的套接字,accept()5.用返回的套接字和客户端进行通讯(send/recv);6.返回并等待另一客户请求。7.关闭套接字。

客户端:1.socket()建立套接字2.向服务器发出连接请求,(connect)2。和服务器进行通信,send()和recv(),在套接字上写读数据,直至数据交换完毕;4closesocket()关闭套接字。

UDP:1服务器端:1.创建套接字(socekt)2.将套接字绑定到本地地址和端口上(bind);3.等待接收数据(recvfrom);4.closesocket()关闭套接字。

客户端:1.创建套接字(socekt)2,向服务器端发送数据(sendto)3.closesocket()关闭套接字。

26、进程间通信类型:

(1)环境变量、文件描述符 一般Unix环境下的父进程执行fork(),生成的子进程拥有了父进程当前设置的环境变量以及文件描述符;由于通信是一个单向的、一次性的通信,随后的父进程以及子进程后续的内容不能再能共享;

(2)命令行参数 大多数用户都使用过ShellExec相关的命令,此API可以打开新的进程,并可以通过接口里的输入参数进行信息共享;同样,他也是一个单项、一次性的通信;

(3)管道 使用文件和写方式访问公用的数据结构;管道分为匿名管道和命名管道,前者是用作关联进程间用,后者为无关联的进程使用;前者通过文件描述符或文件句柄提供对命名管道的访问,后者需要知道管道名称才能读写管道;一般来讲,读写的内容是字节流,需要转换为有意义的结构才有意义;

(4)共享内存 进程需要可以被其他进程访问浏览的进程块;进程间共享内存的关系与函数间共享全局变量的关系类似

(5)DDE 动态数据交互

线程间通信类型:

(1)全局数据;

(2)全局变量;

(3)全局数据结构;

(4)线程间通信的参数:pThread_create这类API接口中的参数

27、vector和list的区别?

vector内部使用数组,访问速度快,但是删除数据比较耗性能

list内部使用链表,访问速度慢,但是删除数据比较快

28、关键字static的作用是什么?

这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用:

1). 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。

2). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。

3). 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。

大多数应试者能正确回答第一部分,一部分能正确回答第二部分,同是很少的人能懂得第三部分。这是一个应试者的严重的缺点,因为他显然不懂得本地化数

据和代码范围的好处和重要性。

Const

29.关键字const是什么含意?

我只要一听到被面试者说:“const意味着常数”,我就知道我正在和一个业余者打交道。去年Dan Saks已经在他的文章里完全概括了const的所有用法,因此ESP(译者:Embedded Systems Programming)的每一位读者应该非常熟悉const能做什么和不能做什么.如果你从没有读到那篇文章,只要能说出const意味着“只读”就可以了。尽管这个答案不是完全的答案,但我接受它作为一个正确的答案。(如果你想知道更详细的答案,仔细读一下Saks的文章吧。)如果应试者能正确回答这个问题,我将问他一个附加的问题:下面的声明都是什么意思?

const int a;

int const a;

const int *a;

int * const a;

int const * a const;

前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。顺带提一句,也许你可能会问,即使不用关键字 const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?我也如下的几下理由:

1). 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。)

2). 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。

3). 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。

30、引用与指针有什么区别?

答 、1) 引用必须被初始化,指针不必。

2) 引用初始化以后不能被改变,指针可以改变所指的对象。

3) 不存在指向空值的引用,但是存在指向空值的指针。

31、上机题

一个5*5的数组,求出每个值8个方向存在的所有数据的中间大的数。比如最上最左的值周围只有3个数,组成数组为[0][1][2]。取第3/2即[1]。

// Test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
using namespace std;

#define M 5

void BubbleSort(int *b, int count)
{
	int i, j;
	for (i=0; i<count-1; i++)
	{
		for (j=count-1; j>i; j--)
		{
			if (b[j] < b[j-1])
			{
				int temp = b[j];
				b[j] = b[j-1];
				b[j-1] = temp;
			}
		}
	}
}

int GetMiddle(int (*a)[M], int m, int n)
{
    int i, j;
	int b[8];
	int count = 0;

	for (i=-1; i<2; i++)
	{
		for (j=-1; j<2; j++)
		{
			if (i == 0 && j == 0)
				continue;

			if ((m+i >= 0) && (m+i <= 4) && (n+j >= 0) && (n+j <= 4))
			{
				b[count++] = a[m+i][n+j];
			}
		}
	}

	BubbleSort(b, count);

	return b[count/2];

}

int main(int argc, char* argv[])
{
	cout << " hello world! " << endl;	 
	int a[M][M] = {
		{12, 54, 32, 67, 123},
		{34, 67, 87, 46, 23},
		{54, 35, 65, 77, 100},
		{98, 3, 79, 128, 98},
		{4, 67, 45, 198, 100}
	};
	int b[M][M];

	int i, j;
	for (i=0; i<M; i++)
	{
		for (j=0; j<M; j++)
		{
			b[i][j] = GetMiddle(a, i, j);
		}
	}

	for (i=0; i<M; i++)
	{
		for (j=0; j<M; j++)
		{
			printf("%4d ", b[i][j]);
		}

		printf("\n");
	}

	return 0;
}




未完待续。http://blog.csdn.net/erick08/article/details/7467799


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值