您当前的位置: 首页 >  c++

phymat.nico

暂无认证

  • 1浏览

    0关注

    1967博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

C++笔试题目大全(笔试宝典)(不断完善中)

phymat.nico 发布时间:2017-12-19 22:44:36 ,浏览量:1

1.new 、 delete 、 malloc 、 free 关系

delete 会调用对象的析构函数 , 和 new 对应 free 只会释放内存, new 调用构造函数。 malloc 与 free 是 C++/C 语言的标准库函数, new/delete 是 C++ 的运算符。它们都可用于申请动态内存和释放内存。对于非内部数据类型的对象而言,光用 maloc/free 无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于 malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于 malloc/free 。因此 C++ 语言需要一个能完成动态内存分配和初始化工作的运算符 new ,以及一个能完成清理与释放内存工作的运算符 delete 。注意 new/delete 不是库函数。

总结:new和delete会自动调用对象的构造与析构函数而malloc与free不会;

      new和delete式C++运算符,而malloc和free是C/C++标准库函数。

2.delete与 delete [] 区别

delete 只会调用一次析构函数,而 delete[] 会调用每一个成员的析构函数。在 More Effective  C++ 中有更为详细的解释:“当 delete 操作符用于数组时,它为每个数组元素调用析构函数,然后调用 operatordelete 来释放内存。” delete 与 New 配套, delete [] 与 new [] 配套

  MemTest*mTest1=newMemTest[10];

  MemTest*mTest2=newMemTest;

  int*pInt1=newint[10];

  int*pInt2=newint;

  delete[]pInt1;  //-1-

  delete[]pInt2;  //-2-

  delete[]mTest1;//-3-

  delete[]mTest2;//-4-

  在 -4- 处报错。

这就说明:对于内建简单数据类型, delete 和 delete[] 功能是相同的。对于自定义的复杂数据类型, delete 和 delete[] 不能互用。 delete[] 删除一个数组, delete 删除一个指针简单来说,用 new 分配的内存用 delete 删除用 new[] 分配的内存用 delete[] 删除 delete[] 会调用数组元素的析构函数。内部数据类型没有析构函数,所以问题不大。如果你在用 delete 时没用括号, delete 就会认为指向的是单个对象,否则,它就会认为指向的是一个数组。

总结: delete 只会调用一次析构函数,而 delete[] 会调用每一个成员的析构函数。

3.C C++ JAVA共同点,不同之处?

4.继承优缺点。

类继承是在编译时刻静态定义的,且可直接使用,类继承可以较方便地改变父类的实现。但是类继承也有一些不足之处。首先,因为继承在编译时刻就定义了,所以无法在运行时刻改变从父类继承的实现。更糟的是,父类通常至少定义了子类的部分行为,父类的任何改变都可能影响子类的行为。如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。

(待补充)

 

5.C++有哪些性质(面向对象特点)

封装,继承和多态。

在面向对象程序设计语言中,封装是利用可重用成分构造软件系统的特性,它不仅支持系统的可重用性,而且还有利于提高系统的可扩充性;消息传递可以实现发送一个通用的消息而调用不同的方法;封装是实现信息隐蔽的一种技术,其目的是使类的定义和实现分离。

6.子类析构时要调用父类的析构函数吗?

析构函数调用的次序是先派生类的析构后基类的析构,也就是说在基类的的析构调用的时候 , 派生类的信息已经全部销毁了定义一个对象时先调用基类的构造函数、然后调用派生类的构造函数;析构的时候恰好相反:先调用派生类的析构函数、然后调用基类的析构函数Java 无析构函数深拷贝和浅拷贝

7.多态,虚函数,纯虚函数

 

8.求下面函数的返回值(微软)

int func(x) {     int countx = 0;     while(x)     {           countx ++;           x = x&(x-1);      }     return countx; } 

假定 x = 9999 。 答案: 8

思路:将 x 转化为 2 进制,看含有的 1 的个数。

9.什么是 “ 引用 ” ?申明和使用 “ 引用 ” 要注意哪些问题?

答:引用就是某个目标变量的 “ 别名 ”(alias) ,对应用的操作与对变量直接操作效果完全相同。申明一个引用的时候,切记要对其进行初始化。引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名的别名。声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。不能建立数组的引用。

10.将 “ 引用 ” 作为函数参数有哪些特点?

( 1 )传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。

( 2 )使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;而使用一般变量传递函数的参数,当发生函数调用时,需要给形参分配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好。

( 3 )使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用 "* 指针变量名 " 的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。

11.在什么时候需要使用 “ 常引用 ” ?  

如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。常引用声明方式: const 类型标识符 & 引用名 = 目标变量名;

例 1

int a ; const int &ra=a; ra=1; // 错误 a=1; // 正确

例 2

string foo( ); void bar(string & s);

那么下面的表达式将是非法的:

bar(foo( )); bar("hello world");

原因在于 foo( ) 和 "hello world" 串都会产生一个临时对象,而在 C++ 中,这些临时对象都是 const 类型的。因此上面的表达式就是试图将一个 const 类型的对象转换为非 const 类型,这是非法的。引用型参数应该在能被定义为 const 的情况下,尽量定义为 const 。

12.将 “ 引用 ” 作为函数返回值类型的格式、好处和需要遵守的规则 ?

格式:类型标识符 & 函数名(形参列表及类型说明) { // 函数体 }

好处:在内存中不产生被返回值的副本;(注意:正是因为这点原因,所以返回一个局部变量的引用是不可取的。因为随着该局部变量生存期的结束,相应的引用也会失效,产生 runtime error! 注意事项:

( 1 )不能返回局部变量的引用。这条可以参照 Effective C++[1] 的 Item 31 。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了 " 无所指 " 的引用,程序会进入未知状态。

( 2 )不能返回函数内部 new 分配的内存的引用。这条可以参照 Effective C++[1] 的 Item 31 。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部 new 分配内存的引用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由 new 分配)就无法释放,造成 memory leak 。

( 3 )可以返回类成员的引用,但最好是 const 。这条原则可以参照 Effective C++[1] 的 Item 30 。主要原因是当对象的属性是与某种业务规则( business rule )相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的非常量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。

( 4 )流操作符重载返回值申明为 “ 引用 ” 的作用:

流操作符 > ,这两个操作符常常希望被连续使用,例如: cout next;

}

}

if(pa->next!=NULL)

ra->next=pa;

if(qa->next!=NULL)

ra->next==qa;

return R;

}

101.用递归算法判断数组 a[N] 是否为一个递增数组。

递归的方法,记录当前最大的,并且判断当前的是否比这个还大,大则继续,否则返回 false 结束:

bool fun( int a[], int n )

{

if( n= =1 )

return true;

if( n= =2 )

return a[n-1] >= a[n-2];

return fun( a,n-1) && ( a[n-1] >= a[n-2] );

}

102.编写算法,从 10 亿个浮点数当中,选出其中最大的 10000 个。

用外部排序,在《数据结构》书上有《计算方法导论》在找到第 n 大的数的算法上加工

103.编写一 unix 程序,防止僵尸进程的出现 .

同学的 4 道面试题,应聘的职位是搜索引擎工程师,后两道超级难,(希望大家多给一些算发)

1. 给两个数组和他们的大小,还有一动态开辟的内存,求交集,把交集放到动态内存 dongtai ,并且返回交集个数

long jiaoji(long* a[],long b[],long* alength,long blength,long* dongtai[])

2. 单连表的建立,把 'a'--'z'26 个字母插入到连表中,并且倒叙,还要打印!

方法 1 :

typedef struct val

{   int date_1;

    struct val *next;

}*p;

 

void main(void)

{   char c;

    

    for(c=122;c>=97;c--)

       { p.date=c;

          p=p->next;

        }

 

    p.next=NULL;

}

}

方法 2 :

node *p = NULL;

node *q = NULL;

 

node *head = (node*)malloc(sizeof(node));

head->data = ' ';head->next=NULL;

 

node *first = (node*)malloc(sizeof(node));

first->data = 'a';first->next=NULL;head->next = first;

p = first;

 

int longth = 'z' - 'b';

int i=0;

while ( idata = 'b'+i;temp->next=NULL;q=temp;

 

head->next = temp; temp->next=p;p=q;

i++;

}

 

print(head);

 

104.可怕的题目终于来了

象搜索的输入信息是一个字符串,统计 300 万输入信息中的最热门的前十条,我们每次输入的一个字符串为不超过 255byte, 内存使用只有 1G ,

请描述思想,写出算发( c 语言),空间和时间复杂度,

7. 国内的一些帖吧,如 baidu, 有几十万个主题,假设每一个主题都有上亿的跟帖子,怎么样设计这个系统速度最好,请描述思想,写出算发( c 语言),空间和时间复杂度,

 

 

#include   string.h

main(void)

{   char   *src="hello,world";

    char   *dest=NULL;

    dest=(char    *)malloc(strlen(src));

    int   len=strlen(str);

    char   *d=dest;

    char   *s=src[len];

    while(len--!=0)

      d++=s--;

    printf("%s",dest);

}

找出错误!!

#include   "string.h"

#include "stdio.h"

#include "malloc.h"

main(void)

{  

char   *src="hello,world";

    char   *dest=NULL;

    dest=(char   *)malloc(sizeof(char)*(strlen(src)+1));

    int   len=strlen(src);

    char   *d=dest;

    char   *s=src+len-1;

    while(len--!=0)

      *d++=*s--;

*d='/0';

    printf("%s",dest);

}

105. 判断字符串是否为回文

bool IsSymmetry(constchar * p)

     {

         assert(p!=NULL);

         const char * q=p;      

         int len=0;

         while (*q++!='/0' )

         {

              len++;

         }       

         bool bSign=true ;

         q=p+len-1;

         if (0=0) && (a=0)&&(a"cba" 2) 写一个函数将 "tom is cat" 将内存中的字符串翻转,即 "cat is tomm" #include #define SPACE ' ' #define ENDL '/0' char* s = "The quick brown fox jumps over the lazy dog";

void str_reverse(char* p1,char* p2){       if(p1==p2)return;     *p1 = (*p1)+(*p2);     *p2 = (*p1)-(*p2);     *p1 = (*p1)-(*p2);       if(p1==p2-1)return;       else str_reverse(++p1,--p2); }

void str_word_reverse(char* str){       char *q1=str, *q2=str, *t;

      while(*q1==SPACE)q1++;       if(*q1==ENDL)return; //!       else q2=q1+1;

      while( (*q2!=SPACE) && (*q2!=ENDL) )q2++;           t=q2--;     str_reverse(q1,q2);

      if(*t==ENDL)return;       else str_word_reverse(t); }

int main(int a ,char** b) {     printf("%s/n",s);     str_reverse(s,s+strlen(s)-1);     printf("%s/n",s);     str_word_reverse(s);     printf("%s/n",s);            return 0; }

Output:

The quick brown fox jumps over the lazy dog god yzal eht revo spmuj xof nworb kciuq ehT dog lazy the over jumps fox brown quick The

---------------------------------------------------------------------- 今天同学又问一道题 , 和上面有些类似,但是要求更严格了一些: 写一个递归函数将内存中的字符串翻转 "abc"->"cba", 并且函数原型已确定: void reverse(char* p) 其实,要求越多,思路越确定,我的解如下: #include #include char* s = "0123456789"; #define ENDL '/0' void reverse(char* p){        // 这是这种方法的关键,使用 static 为的是能用 str_reverse 的思路,但是不好        static char* x=0;        if(x==0)x=p;        char* q = x+strlen(p)-1;        if(p==q)return;        *q=(*p)^(*q);        *p=(*p)^(*q);        *q =(*p)^(*q);        if(q==p+1)return;        reverse(++p); } // 这种方法就直观多了,但是当字符串很长的时候就很低效 void reverse2(char* p){        if(*(p+1)==ENDL)return;        for(char* o=p+strlen(p)-1,char t=*o;o!=p;o--)           *o=*(o-1);        *p=t;        reverse2(p+1); }

int main(int c,char** argv){        reverse2(s);        printf("%s/n",s);        return 0; }

 

114. 交换两个数的宏定义

 

交换两个参数值的 宏定义 为:. #define SWAP (a,b) (a)=(a)+(b);(b)=(a)-(b);(a)=(a)-(b);

 

115.Itearator 各指针的区别

 

游标和指针

我说过游标是指针,但不仅仅是指针。游标和指针很像,功能很像指针,但是实际上,游标是通过重载一元的 ”*” 和 ”->” 来从容器中间接地返回一个值。将这些值存储在容器中并不是一个好主意,因为每当一个新值添加到容器中或者有一个值从容器中删除,这些值就会失效。在某种程度上,游标可以看作是句柄( handle )。通常情况下游标( iterator )的类型可以有所变化,这样容器也会有几种不同方式的转变:

iterator—— 对于除了 vector 以外的其他任何容器,你可以通过这种游标在一次操作中在容器中朝向前的方向走一步。这意味着对于这种游标你只能使用 “++” 操作符。而不能使用 “--” 或 “+=” 操作符。而对于 vector 这一种容器,你可以使用 “+=” 、 “—” 、 “++” 、 “-=” 中的任何一种操作符和 “=” 、 “==” 、 “!=” 等比较运算符。

 

116. C++ 中的 class 和 struct 的区别

从语法上,在 C++ 中(只讨论 C++ 中)。 class 和 struct 做类型定义时只有两点区别: (一)默认继承权限。如果不明确指定,来自 class 的继承按照 private 继承处理,来自 struct 的继承按照 public 继承处理; (二)成员的默认访问权限。 class 的成员默认是 private 权限, struct 默认是 public 权限。 除了这两点, class 和 struct 基本就是一个东西。语法上没有任何其它区别。

不能因为学过 C 就总觉得连 C++ 中 struct 和 class 都区别很大,下面列举的说明可能比较无聊,因为 struct 和 class 本来就是基本一样的东西,无需多说。但这些说明可能有助于澄清一些常见的关于 struct 和 class 的错误认识: ( 1 )都可以有成员函数;包括各类构造函数,析构函数,重载的运算符,友元类,友元结构,友元函数,虚函数,纯虚函数,静态函数; ( 2 )都可以有一大堆 public/private/protected 修饰符在里边; ( 3 )虽然这种风格不再被提倡,但语法上二者都可以使用大括号的方式初始化:

A a = {1, 2, 3}; 不管 A 是个 struct 还是个 class ,前提是这个类 / 结构足够简单,比如所有的成员都是 public 的,所有的成员都是简单类型,没有显式声明的构造函数。 ( 4 )都可以进行复杂的继承甚至多重继承,一个 struct 可以继承自一个 class ,反之亦可;一个 struct 可以同时继承 5 个 class 和 5 个 struct ,虽然这样做不太好。 ( 5 )如果说 class 的设计需要注意 OO 的原则和风格,那么没任何理由说设计 struct 就不需要注意。 ( 6 )再次说明,以上所有说法都是指在 C++ 语言中,至于在 C 里的情况, C 里是根本没有 “class” ,而 C 的 struct 从根本上也只是个包装数据的语法机制。 ---------------------------------------------------------------

最后,作为语言的两个关键字,除去定义类型时有上述区别之外,另外还有一点点: “class” 这个关键字还用于定义模板参数,就像 “typename” 。但关键字 “struct” 不用于定义模板参数。

 

关于使用大括号初始化

   class 和 struct 如果定义了构造函数的话,都不能用大括号进行初始化

  如果没有定义构造函数, struct 可以用大括号初始化。

  如果没有定义构造函数,且所有成员变量全是 public 的话,可以用大括号初始化。

  关于默认访问权限

   class 中默认的成员访问权限是 private 的,而 struct 中则是 public 的。

  关于继承方式

   class 继承默认是 private 继承,而 struct 继承默认是 public 继承。

  关于模版

 

  在模版中,类型参数前面可以使用 class 或 typename ,如果使用 struct ,则含义不同, struct 后面跟的是 “non-type template parameter” ,而 class 或 typename 后面跟的是类型参数。

 

class 中有个默认的 this 指针, struct 没有 不同点:构造函数,析构函数  this  指针

 

117. 有关重载函数

 

返回值类型不同构不成重载 参数参数顺序不同能构成重载

c++ 函数同名不同返回值不算重载!函数重载是忽略返回值类型的。 --------------------------------------------- 成员函数被重载的特征有: 1) 相同的范围(在同一个类中); 2) 函数名字相同; 3) 参数不同; 4) virtual 关键字可有可无。

5) 成员函数中 有无 const ( 函数后面 ) 也可判断是否重载

 

118. 数据库与 T-SQL 语言    

关系数据库是表的集合,它是由一个或多个关系模式定义。 SQL 语言中的数据定义功能包括对数据库、基本表、视图、索引的定义。

 

119. 关系模型的基本概念

  关系数据库以关系模型为基础,它有以下三部分组成:     ● 数据结构 —— 模型所操作的对象、类型的集合     ● 完整性规则 —— 保证数据有效、正确的约束条件     ● 数据操作 —— 对模型对象所允许执行的操作方式     关系( Relation )是一个由行和列组成的二维表格,表中的每一行是一条记录( Record ),每一列是记录的一个字段( Field )。表中的每一条记录必须是互斥的,字段的值必须具有原子性。

120.SQL 语言概述

    SQL (结构化查询语言)是关系数据库语言的一种国际标准,它是一种非过程化的语言。通过编写 SQL ,我们可以实现对关系数据库的全部操作。     ● 数据定义语言( DDL ) —— 建立和管理数据库对象     ● 数据操纵语言( DML ) —— 用来查询与更新数据     ● 数据控制语言( DCL ) —— 控制数据的安全性

 

起来是一个很简单的问题,每一个使用过 RDBMS 的人都会有一个概念。

事务处理系统的典型特点是具备 ACID 特征。 ACID 指的是 Atomic (原子的)、 Consistent (一致的)、 Isolated (隔离的)以及 Durable (持续的),它们代表着事务处理应该具备的四个特征:

原子性:组成事务处理的语句形成了一个逻辑单元,不能只执行其中的一部分

一致性:在事务处理执行之前和之后,数据是一致的。

隔离性:一个事务处理对另一个事务处理没有影响。

持续性:当事务处理成功执行到结束的时候,其效果在数据库中被永久纪录下来。

 

121.C 语言中结构化程序设计的三种基本控制结构

 

顺序结构 选择结构 循环结构

 

122.CVS 是什么

 

cvs ( Concurrent Version System ) 是一个版本控制系统。使用它,可以记录下你的源文件的历史。 例如,修改软件时可能会不知不觉混进一些 bug ,而且可能过了很久你才会察觉到它们的存在。有了 cvs ,你可以很容易地恢复旧版本,并从中看出到底是哪个修改导致了这个 bug 。有时这是很有用的。 CVS 服务器端对每个文件维护着一个修订号 , 每次对文件的更新,都会使得文件的修订号加 1 。在客户端中也对每个文件维护着一个修订号 ,CVS 通过这两个修订号的关系,来进行 Update,Commit 和发现冲突等操作操作

 

123. 三种基本的数据模型

 

按照数据结构类型的不同,将数据模型划分为层次模型、网状模型和关系模型。

 

欢迎访问:http://store.taobao.com/shop/view_shop-3b35c083b127c4a2650d942b967cf8c1.htm?nekot=g%2Cm5swy5jrgeydc1248248030084

关注
打赏
1659628745
查看更多评论
立即登录/注册

微信扫码登录

0.0504s