弘连面经

1.引用和指针的区别:

(1)非空区别。引用在使用之前必须要初始化,在任何情况下都不能使用指向空值的引用。
(2)合法性区别。在使用引用之前不需要测试它的合法性。相反,指针则应该总是被测试,防止其为空。
(3)可修改区别。指针可以被重新赋值以指向另一个不同的对象。但是引用则总是指向在初始化时被指定的对象,以后不能改变,但是指定的对象其内容可以改变。
(4)使用区别。指针需要分配内存,引用不用;有const指针的修饰,引用没有。

2.结构体和类的区别:

c 与c++中结结构体的区别:
(1)C的结构体内不允许有函数存在,C++允许有内部成员函数,且允许该函数是虚函数。所以C的结构体是没有构造函数、析构函数、和this指针的。
(2)C的结构体对内部成员变量的访问权限只能是public,而C++允许public,protected,private三种。
(3)C语言的结构体是不可以继承的,C++的结构体是可以从其他的结构体或者类继承过来的。
 C的结构体只是把数据变量给包裹起来了,并不涉及算法。而C++是把数据变量及对这些数据变量的相关算法给封装起来,并且给对这些数据和类不同的访问权限。
C++的结构体和C++类的区别
(1)C++结构体内部成员变量及成员函数默认的访问级别是public,而c++类的内部成员变量及成员函数的默认访问级别是private。
(2) C++结构体的继承默认是public,而c++类的继承默认是private。
3.malloc free 和new delete的区别
  (1)操作对象不一样:malloc与free是C++/C 语言的标准库函数,new/delete 是C++的运算符。对于非内部数据类的对象而言,光用maloc/free 无法满足动
态对象的要求。对象在创建的同时要自动执行构造函数, 对象消亡之前要自动执行析构函数。由于malloc/free 是库函数而不是运算符,不在编译器控制权限之内,
不能够把执行构造函数和析构函数的任务强加malloc/free。
  (2)使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要显式地指出所需内存的尺寸。
  (3)返回类型new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存
分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。
  (4)分配失败,new内存分配失败时,会抛出bac_alloc异常。malloc分配内存失败时返回NULL。
  (5)自定义类型:new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义
类型指针。delete先调用析构函数,然后调用operator delete函数释放内存(通常底层使用free实现)。malloc/free是库函数,
只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构工作。
  (6)重载:C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用
构造函数完成初始化工作,并返回此地址。而malloc不允许重载。
  (7)内存区域:new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一
个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C
语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。

3.atoi函数的实现:

 
int my_atoi(char* pstr)
{
	int Ret_Integer = 0;
	int Integer_sign = 1;
	
	/*
	* 判断指针是否为空
	*/
	if(pstr == NULL)
	{
		printf("Pointer is NULL\n");
		return 0;
	}
	
	/*
	* 跳过前面的空格字符
	*/
	while(isspace(*pstr) == 0)
	{
		pstr++;
	}
	
	/*
	* 判断正负号
	* 如果是正号,指针指向下一个字符
	* 如果是符号,把符号标记为Integer_sign置-1,然后再把指针指向下一个字符
	*/
	if(*pstr == '-')
	{
		Integer_sign = -1;
	}
	if(*pstr == '-' || *pstr == '+')
	{
		pstr++;
	}
	
	/*
	* 把数字字符串逐个转换成整数,并把最后转换好的整数赋给Ret_Integer
	*/
	while(*pstr >= '0' && *pstr <= '9')
	{
		Ret_Integer = Ret_Integer * 10 + *pstr - '0';
		pstr++;
	}
	Ret_Integer = Integer_sign * Ret_Integer;
	
	return Ret_Integer;
}
4.冒泡排序:
    void bubble_sort(int arr[], int len) {  
        int i, j;  
        for (i = 0; i < len - 1; i++)          //外层循环控制趟数,总趟数为len-1
            for (j = 0; j < len - 1 - i; j++)  //内层循环为当前i趟数 所需要比较的次数
                if (arr[j] > arr[j + 1])  
                    swap(arr[j], arr[j + 1]);          
    }  

5.int ,char,size_t在32/64位下分别占用

 16位平台  最大2^16
char         1个字节8位 
short        2个字节16位 
int          2个字节16位 
long         4个字节32位 
指针         2个字节16位  

32位平台  最大2^32
char         1个字节8位 
short        2个字节16位 
int          4个字节32位 
long         4个字节32位
long long    8个字节64位  
指针         4个字节32位

64位平台  最大2^64
char         1个字节 
short        2个字节
int          4个字节  
long         8个字节(区别) 
long long    8个字节  
指针         8个字节(区别)

size_t在32位系统中占4个字节,而在64位系统占8个字节
  #define __SIZE_TYPE  long unsigned int
........................
typedef __SIZE_TYPE__  size_t;
//   其实是无符号长整型

6.linux/window下的线程和进程怎么创建

  对于windows来说,进程和线程的概念都是有着明确定义的,进程的概念对应于一个程序的运行实例(instance),而线程则是程序代码执行的最小单元。也就是说
windows对于进程和线程的定义是与经典OS课程中所教授的进程、线程概念相一致的。
  提供API,CreateThread()用于建立一个新的线程,传递线程函数的入口地址和调用参数给新建的线程,然后新线程就开始执行了。
  windows下,一个典型的线程拥有自己的堆栈、寄存器(包括程序计数器PC,用于指向下一条应该执行的指令在内存中的位置),而代码段、数据段、打开文件这些
进程级资源是同一进程内多个线程所共享的。因此同一进程的不同线程可以很方便的通过全局变量(数据段)进行通信,大家都可以对数据段进行读写,这很方便,也被
在安全性方面诟病,因为它要求程序员时刻意识到这些数据不是线程独立的。
  对于linux来说,则没有很明确的进程、线程概念。首先linux只有进程而没有线程,然而它的进程又可以表现得像windows下的线程。linux利用fork()和exec函
数族来操作多线程。fork()函数可以在进程执行的任何阶段被调用,一旦调用,当前进程就被分叉成两个进程——父进程和子进程,两者拥有相同的代码段和暂时相同的数
据段(虽然暂时相同,但从分叉开的时刻就是逻辑上的两个数据段了,之所以说是逻辑上的,是因为这里是“写时复制”机制,也就是,除非万不得已有一个进程对数据
段进行了写操作,否则系统不去复制数据段,这样达到了负担最小),两者的区别在于fork()函数返回值,对于子进程来说返回为0,对于父进程来说返回的是子进程
id,因此可以通过if(fork()==0)…else…来让父子进程执行不同的代码段,从而实现“分叉”。
exec函数族的函数的作用则是启动另一个程序的新进程,然后完全用那个进程来代替自己(代码段被替换,数据段和堆栈被废弃,只保留原有进程id)。这样,如果在
fork()之后,在子进程代码段里用exec启动另一个进程,就相当于windows下的CreateThread()的用处了,所以说linux下的进程可以表现得像windows下的线程
。
然而linux下的进程不能像windows下线程那样方便地通信,因为他们没有共享数据段、地址空间等。它们之间的通信是通过所谓IPC(InterProcess 
Communication)来进行的。具体有管道(无名管道用于父子进程间通信,命名管道可以用于任意两个进程间的通信)、共享内存(一个进程向系统申请一块可以被共
享的内存,其它进程通过标识符取得这块内存,并将其连接到自己的地址空间中,效果上类似于windows下的多线程间的共享数据段),信号量,套接字

创建线程:

#ifdef __GNUC__
//Linux
#include <pthread.h>
#define CreateThreadEx(tid,threadFun,args) pthread_create(tid, 0, threadFun, args)
#define CloseHandle(ph)
/*
int pthread_create(
  //指向线程标识符的指针。
  pthread_t *restrict tidp,
  //设置线程属性。传入NULL表示使用默认。
  const pthread_attr_t *restrict_attr,
  //新线程所执行的线程函数地址。
  void*(*start_rtn)(void*),
  //传给线程函数的参数。
  void *restrict arg
);*/
#else
//windows
#include <process.h>
#define CreateThreadEx(tid,threadFun,args) _beginthreadex(tid, 0, threadFun, args, 0, NULL)
/*
HANDLE WINAPI _beginthreadex(
  //线程内核对象的安全属性,一般传入NULL表示使用默认设置。
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  //线程栈空间大小。传入0表示使用默认大小(1MB)。
  SIZE_T dwStackSize,
  //新线程所执行的线程函数地址,多个线程可以使用同一个函数地址。
  LPTHREAD_START_ROUTINE lpStartAddress,
  //传给线程函数的参数。
  LPVOID lpParameter,
  //指定额外的标志来控制线程的创建,为0表示线程创建之后立即就可以进行调度,如果为CREATE_SUSPENDED则表示线程创建后暂停运行,
  //这样它就无法调度,直到调用ResumeThread()。
  DWORD dwCreationFlags,
  //返回线程的ID号,传入NULL表示不需要返回该线程ID号。
  LPDWORD lpThreadId
);*/
#endif

7.multable的作用

在C++中,mutable 是为了突破 const 的限制而设置的。可以用来修饰一个类的成员变量。被 mutable 修饰的变量,将永远处于可变的状态,即使是 const 函数
中也可以改变这个变量的值。

8.http中的错误码分别代表是

https://blog.csdn.net/xiong9999/article/details/54138387

9.socket如何实现传输

https://blog.csdn.net/zhang___yong/article/details/78702559

10.TCP/IP协议有那几层

(1)应用层:应用程序通过这一层访问网络,常见 FTP、HTTP、DNS 和 TELNET 协议;

(2)传输层:TCP 协议和 UDP 协议;

(3)网络层:IP 协议,ARP、RARP 协议,ICMP 协议等;

(4)网络接口层:是 TCP/IP 协议的基层,负责数据帧的发送和接收。

https://blog.csdn.net/MXSKE/article/details/78279071

11.右值引用的用法,std::move

https://blog.csdn.net/booirror/article/details/45057689

12.char 和wchar_t的区别

char占一个字节,只能表示256个字符,类似与汉字这种字符char是无法表示的,wchar_t在我的64位机器上占4字节,用于表示更多的字符。

13.GBK,UTF-8,UTF-16一个字符占用多少个字节

https://www.cnblogs.com/wpcockroach/p/3907324.html

utf-8中文字符占三个字节,GB18030兼容GBK兼容GB2312中文字符占两个字节,ISO8859-1是拉丁字符(ASCII字符)占一个字节



猜你喜欢

转载自blog.csdn.net/qq_38446366/article/details/80977865