• 14
  • 14
分享
  • c++笔试题及答案——软件测试圈
  • 恬恬圈 2022-03-10 11:46:36 字数 3811 阅读 1446 收藏 14

1.如何判断一个单链表是有环的?

struct ListNode
{
int key;
ListNode* next;
};
bool check(ListNode* head) //return false : 无环;true: 有环
{
}
答案:一种O(n)的办法就是(搞两个指针,一个每次递增一步,一个每次递增两步,如果有环的话两者必然重合,反之亦然):
bool check(ListNode* head)
{
if (head == NULL) return false;
ListNode *low = head, *fast = head->next;
while (fast != NULL && fast->next != NULL)
{
low = low->next;
fast = fast->next->next;
if (low == fast) return true;
}
return false;
}

2. C++的空类,默认产生哪些类成员函数?

class Empty
{
public:
Empty();                              //缺省构造函数
Empty(const Empty& );             //拷贝构造函数
~Empty();                             //虚构函数
Empty& operator(const Empty& )      //赋值运算符
Empty& operator&();                 //取址运算符
const Empty* operator&() const;     // 取址运算符 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 countx = 0;
char s[64] = { 0 };
while (x)
{
countx++;
x = x&(x - 1);
}
return countx;
}
 
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
char str[] = "world"; cout << sizeof(str) << ": ";
char *p = str; cout << sizeof(p) << ": ";
char i = 10; cout << sizeof(i) << ": ";
void *pp = malloc(10); cout << sizeof(p) << endl;
}

答:6:4:1:4

16. main 主函数执行完毕后,是否可能会再执行一段代码,给出说明?

答:可以用_onexit 注册一个函数,它会在main 之后执行int fn1(void), fn2(void)

int fn1(void)
{
printf("fn1()\n");
return 0;
}
int fn2(void)
{
printf("fn2()\n");
return 0;
}
 
int main()
{
_onexit(fn1);
_onexit(fn2);
printf( "This is executed first.\n" );
}

17.  i最后等于多少?

int i = 1;
int j = i++;
if((i>j++) && (i++ == j)) i+=j;

答:i = 5


文章来源:百度文库

  • 【留下美好印记】
    赞赏支持
登录 后发表评论
+ 关注

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          • 在编写 Junit 测试时,我采用了同一套格式。如此,对于测试用例我就可以遵循这套格式进行编写和阅读,使所有的测试都整体划一。这种格式模板可以帮助我更快的编写测试,提高工作效率。今天我就与大家分享我的这套格式模板。(译者评:与我在测试建设原则中提出的继承原则相同,都是在进行一项测试工作之前,将公共的进行提取,统一格式模板,然后在以后的测试活动中都继承这套模板开展。)文件格式首先,在项目的测试包下新建一个测试文件/测试类,并且创建测试方法。在编写测试文件/测试类时,所有的测试文件/测试类都以 Test 结束,这样会容易理解其是一个测试文件/测试类,也方便后期维护时查看,编辑。例如一个名字为&nb...
            14 14 1814
            分享
          •   一、缓存测试  缓存系统的使用,在一定程度上,极大的提升了应用程序的性能和效率,在秒杀系统的建设上,缓存系统出力不小,特别是数据查询方面,数据的快速返回广受好评。但同时,它也带来了一些问题,测试过程中,如果没有及时关注到缓存系统,整个测试环节是有遗漏的。缓存系统没有经过严格的测试,容易产生一个严重的问题,就是数据的一致性问题。如果没有对缓存系统进行测试,并且后端系统对数据的一致性要求很高,那么就不能使用缓存。  缓存的主要作用:是将业务系统的数据处理结果,暂时在内存中保存,并且等待下次访问的时候,立马从内存中取出。在日常开发场景中,因为服务器的性能或者自身业务对数据处理非常耗时的时候,当发...
            14 15 1847
            分享
          • 前言有位同事曾经很认真地问过我一个问题。他说他现在从事软件测试工作已经4年了,但是他不知道现在的工作和自己在工作3年时有什么不同,此外他还想知道他做软件测试工作到第5年或第6年会怎么样。后来他在工作到第5年的时候转岗了。虽然他已经转岗了,后来联系时他又问了我这个问题,似乎这个问题困惑他很深、很久了。这件事情对我的触动很大,我相信这个问题是带有一定普遍性的。软件测试是一个缺乏发展空间、做到一定阶段后只能通过 “转岗” 来寻找发展机会的职业吗?肯定不是。Martin Pol, 欧洲业界公认的“ Test Guru” (大佬,精神领袖),1998 年欧洲第一届杰出测试贡献奖获得者,并获得英国骑士勋章...
            12 12 1474
            分享
          • 现在很多人,等不及。现在很多人,不想等。外面的广告更加夸张,我要的现在就要。真是chedan。搞什么假惺惺不懂都要付出时间。把时间这个变量狠狠地抛诸脑后,定会受到时间狠狠地鞭打,让你好好停下来,等等时间。等,本来就是行动计划的一部分。心里没数,就等不及;心里没底,就等不起;肚里没货,就等不了;胸中没有战略,就等不下。急,不是因为真的急,而是不知道该干嘛。一切尽在咫尺,不是所有的事情都尽在掌握。《孙子兵法》说先计算,看看自己有多少胜算的把握,算出来可胜,行啦,这个时候再动;算出来,把握不大,不要动,等到时机成熟的时候,再动;等到能动的时候再动。不到亮剑的时候,就摩拳擦掌,就“磨刀霍霍向猪羊”,也...
            1 1 826
            分享
          • 1、引言小屌丝:鱼哥,我想请教一个问题。小鱼:国庆假期你经历了什么,让你变得如此的 "善良"?小屌丝:别这么说,我一直很善良,至少,很正直....小鱼:打住,直接点, 你有什么需要帮助的?小屌丝:我就是想把查询的结果也入到excel表中小鱼:然后呢?小屌丝:sqlserver数据库。小鱼:......好吧,还有其他要求吗?小屌丝:没有了。小鱼:OK,我就花费几分钟,给你整一个。 2、代码实战 2.1 openpyxl写入excel 2.1.1 安装凡是涉及第三方库,必须需要安装,老规矩,直接pip安装pip install ...
            0 0 893
            分享
      • 51testing软件测试圈微信