2018年8月22日
目录
1.C++中定义一个空类,则编译器默认为该类提供了几个构造函数(默认构造函数)?提供一个默认的参构造函数
2.C++中空结构体和空类的sizeof()值?
3.关于动态链接库DLL的知识:主要问dll与主调程序间的影响关系
4.C:老生常谈:通过指针引用多维数组,数组指针
5.函数指针
6.让人头疼的const,但const很好。
7.指针引用(指针变量的引用!)
8.C字符串转义字符:
9.C++类对象的构造函数的说法判断:
10.什么是WebService?WebService是基于TCP/IP 的吗?
11.套接字编程中的listen函的第二个参数是什么?请求队列的最大长度。
12.哪些STL容器具有find()成员函数?
13.线程同步
14.TCP/IP协议组
15.线程池以dll的形式使用才更高效?(这尼玛神马问题!)
16.类、结构的内存自己对齐问题!
1.C++中定义一个空类,则编译器默认为该类提供了几个构造函数(默认构造函数)?提供一个默认的参构造函数
参考[1]https://blog.csdn.net/china_jeffery/article/details/79288103
2.C++中空结构体和空类的sizeof()值?
#include<iostream>
using namespace std;
struct sEmpty{};
class cEmpty{};
int mian()
{
//Win32:以下两行都输出1,,,x64下也是1
cout << "sizeof(sEmpty)=" << sizeof(sEmpty) << endl;
cout << "sizeof(cEmpty)=" << sizeof(cEmpty) << endl;
}
3.关于动态链接库DLL的知识:主要问dll与主调程序间的影响关系
参考[2]动态库DLL详解https://blog.csdn.net/wang15061955806/article/details/50877318
#pragma comment(lib,"a.lib")
#pragma peak(n) //内存对齐方式
4.C:老生常谈:通过指针引用多维数组,数组指针
行指针:指向一整个一维数组!
如指向又m个元素组成的一维度数组的指针变量:
int (*p)[3];//是指向整个包含3个元素组成的一维度数组的指针变量,是行指针
注意:p指向第一行{1,2,3}
p+1指向第二行{4,5,6}
int n[][3] = { 1, 2, 3, 4, 5, 6 };
int (*p)[3];//数组指针变量p,p指向一维度数组。p本身是指针的指针,即2级指针!
p = n;
cout << "p[0][0]=" << p[0][0] << endl;//1 p[0][0]=1
cout << "*(p[0]+1)=" << *(p[0] + 1) << endl;//2 *(p[0]+1)=2
cout << "(*p)[2]=" << (*p)[2] << endl;//3 (*p)[2]=3
//p本身是指针的指针,即2级指针!接引用一次p,则的行指针,即*p是个行指针,指向第一个元素n[0][0]
cout << "*p[0]=" << *p[0] << endl;//*p[0]=1
cout << "**p=" << **p << endl;//**p=1
cout << "p[1][0]=" << p[1][0] << endl;//p[1][0]=4
cout << "*(*(p+1)+0)=" << *(*(p + 1) + 0) << endl;//*(*(p+1)+0)=4
5.函数指针
int func(int,int)
我要定义一个指针,指向func函数:
int(*p)(int,int);
p=func;
int func(int x, int y)
{
return x + y;
}
int main()
{
int(*p)(int, int);//函数指针p
p = func;
cout << "x+y=" << func(2, 3) << endl;
cout << "x+y=" << p(2, 3) << endl;
/*x+y=5
x+y=5*/
}
6.让人头疼的const:
6.1。指向常量的指针变量p:const int *p;和int const *p; //const在*左侧
int a = 2;
int b = 3;
//const int *p;//指向常量的指针p,即不能通过指针p修改其所指对象!const int *p等同于int const *p
int const *p;
p = &a;
cout << *p << endl;
p = &b;
//*p = 5;//错误!表达式必须是可修改的左值
6.2。常指针,常量指针,即指针本身的值不可修改://const在*右侧
//常量指针:即指针本身是常量,常指针,不可以更改其值的指针!
//常指针必须在定义的时候初始化,此后不可更改其值!
//int* const p;//错误,变量p需要初始值设定项
int* const cp = &a;
*cp = 5;
cout << "a=" << a << endl;//a=5
//cp = &b;//错误!表达式必须是可修改的左值
6.3。指向常量的常指针:
int const * const ccp = &a;//ccp:指向常量的常指针
7.指针引用(指针变量的引用!)
//指针是变量,像int a;a就是一int型变量,引用int & ra=a;就让a和ra同等
//指针引用就是指针变量的引用!即让rpa和pa同等!
int *pa = &a;
int*& rpa = pa;
cout << "*pa="<<*pa << endl;
cout << "*rpa=" << *rpa << endl;
/*
*pa=5
*rpa=5
*/
pa = nullptr;
cout << "*rpa=" << *rpa << endl;
//运行时报错: 0xC0000005: 读取位置 0x00000000 时发生访问冲突。
查看指针与引用的区别[1]https://blog.csdn.net/m0_37357063/article/details/81910935
8.C字符串转义字符:
char* str = "hik\vision\\2\018";//hik\vision\\2没有发转义,正好13个字符?
cout << "sizeof(str)=" << sizeof(str) << endl;
cout << "strlen(str)=" << strlen(str) << endl;
/*
sizeof(str)=4
strlen(str)=13
*/
char* str2 = "\\";
char str2Array[] = "\\";
cout << "strlen(str2)=" << strlen(str2) << endl;//strlen(str2)=1
cout << "sizeof(str2)=" << sizeof(str2) << endl;//sizeof(str2)=4
cout << "sizeof(str2Array)=" << sizeof(str2Array) << endl;//sizeof(str2Array)=2
char* str3 = "\v";
cout << "strlen(str3)=" << strlen(str3) << endl;//strlen(str3)=1
cout << "sizeof(str3)=" << sizeof(str3) << endl;//sizeof(str3)=4
char* str4 = "\0";
cout << "strlen(str4)=" << strlen(str4) << endl;//strlen(str4)=0
cout << "sizeof(str4)=" << sizeof(str4) << endl;//sizeof(str4)=4
char strArray[] = "hik\vision\\2\018";
cout << "sizeof(strArray)=" << sizeof(strArray) << endl;
cout << "strlen(strArray)=" << strlen(strArray) << endl;
/*
sizeof(strArray)=14
strlen(strArray)=13
*/
9.C++类对象的构造函数的说法判断:
- 构造函数可以重载吗?可以
- 构造函数可以是内联函数吗?可以,在类定义里实现就是内联函数!类定义里实现不一定非要加inline
- 构造函数可以设置默认的参数吗?可以
10.什么是WebService?WebService是基于TCP/IP 的吗?
11.套接字编程中的listen函的第二个参数是什么?
C函数listen():伯克利套接字:
#include <sys/types.h>
#include <sys/socket.h>
int listen(SOCKET sockfd, int backlog);
参数
sockfd 一个已绑定未被连接的套接字描述符
backlog 连接请求队列(queue of pending connections)的最大长度(一般由2到4),用SOMAXCONN则由系统确定。
返回值
无错误,返回0,
否则,返回SOCKET ERROR,可以调用函数WSAGetLastError取得错误代码。WSAGetLastError是MFC中的函数!
说明
(1) 执行listen 之后套接字进入被动模式。
(2) 队列满了以后,将拒绝新的连接请求。客户端将出现连接D 错误WSAECONNREFUSED。
(3) 在正在listen的套接字上执行listen不起作用。
12.哪些STL容器具有find()成员函数?
set、map、string等有find()成员函数;vector、list、deque都没有find成员函数。
//哪些STL容器具有find成员函数
//vector<int> vecInt;
//vecInt.find();
//list<int> lsInt;
//lsInt.find();//没有find成员
//deque<int> dqInt;
//dqInt.find();//没有find成员
map<int> mpInt;
mpInt, find();//有find成员,只是参数不对
/*
template<class _InIt,
class _Ty> inline
_InIt find(_InIt _First, _InIt _Last, const _Ty& _Val)
{ // find first matching _Val
_DEBUG_RANGE(_First, _Last);
return (_Rechecked(_First,
_Find(_Unchecked(_First), _Unchecked(_Last), _Val)));
}
*/
set<int> stInt;
stInt.find();//有find成员,只是参数不对
/*
const_iterator find(const key_type& _Keyval) const
{ // find an element in nonmutable sequence that matches _Keyval
const_iterator _Where = lower_bound(_Keyval);
return (_Where == end()
|| _DEBUG_LT_PRED(this->_Getcomp(),
_Keyval, this->_Key(_Where._Mynode()))
? end() : _Where);
}
*/
13.线程同步
临界区
互斥量
事件对象
哪些只能用于一个进程中的线程同步?
哪些可以用于多个进程间的同步?
参考我的博文:[1]https://blog.csdn.net/m0_37357063/article/details/80695303
MFC 线程间的同步
使得隶属于同一个进程的多个线程协调一致地工作称为线程的同步。
常用的同步对象有临界区(Critical Section)、互斥(Mutex)、信号量(Semaphore)和事件(Event)。
MFC提供了同步类和同步辅助类,这些类要含义头文件afxmt.h
表1MFC支持多线程同步的同步类
类名 | 说明 |
基类CSyncObject | 同步对象的基类,抽象类,为Win32中的同步对象提供通用性能 |
临界区类CCriticalSection | 在同一时间内仅有一个线程被允许修改数据或使用某些其他控制资源,用于保护共享资源 |
互斥类CMutex | 有多个进程同时存取相应资源时使用,用于保护共享资源 |
信号类CSemaphore | 一个应用允许同时有多个线程访问相应资源时使用,主要用于资源计数 |
事件类CEvent | 某个线程必须等待某些事情发生以后才能存取相应资源时使用,协调多个线程间的动作 |
同步辅助类CSingleLock、CMultiLock | 用于在一个多线程程序中控制对资源的访问,当在同一个时间只需等待一个同步化对象时使用CSingleLock类,否则使用CMultiLock |
14.熟悉TCP/IP协议组
网络层哪些协议(IP、ICMP、ARP)
参考我的博文:[1]https://blog.csdn.net/m0_37357063/article/details/80657591
15.线程池以dll的形式使用才更高效?(这尼玛神马问题!)
16.类、结构的内存自己对齐问题!
#program peak(n);
sizeof()问题!
在所有的预处理指令中,#pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。
参考[1]https://baike.baidu.com/item/%23pragma
在网络协议编程中,经常会处理不同协议的数据报文。一种方法是通过指针偏移的方法来得到各种信息,但这样做不仅编程复杂,而且一旦协议有变化,程序修改起来也比较麻烦。在了解了编译器对结构空间的分配原则之后,我们完全可以利用这一特性定义自己的协议结构,通过访问结构的成员来获取各种信息。这样做,不仅简化了编程,而且即使协议发生变化,我们也只需修改协议结构的定义即可,其它程序无需修改,省时省力。下面以TCP协议首部为例,说明如何定义协议结构。
其协议结构定义如下:
#pragma pack(1)//按照1字节方式进行对齐
struct TCPHEADER
{
shortSrcPort;//16位源端口号
shortDstPort;//16位目的端口号
intSerialNo;//32位序列号
intAckNo;//32位确认号
unsignedcharHaderLen:4;//4位首部长度
unsignedcharReserved1:4;//保留16位中的4位
unsignedcharReserved2:2;//保留16位中的2位
unsignedcharURG:1;
unsignedcharACK:1;
unsignedcharPSH:1;
unsignedcharRST:1;
unsignedcharSYN:1;
unsignedcharFIN:1;
shortWindowSize;//16位窗口大小
shortTcpChkSum;//16位TCP检验和
shortUrgentPointer;//16位紧急指针
};
#pragm apop()//取消1字节对齐方式
sizeof(TCPHEADER)=20 //TCP首部固定长度为20字节!
#pragma pack规定的对齐长度,实际使用的规则是: 结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。 但是,当#pragma pack的值等于或超过最长数据成员的长度的时候,这个值的大小将不产生任何效果。 而结构整体的对齐,则按照结构体中最大的数据成员进行。
#pragma pack(1)
using namespace std;
/*
#pragma pack规定的对齐长度,实际使用的规则是:
结构,联合,或者类的数据成员,第一个放在偏移为0的地方,
以后每个数据成员的对齐,按照#pragma pack指定的数值和这个数据成员自身长度中,
比较小的那个进行。 但是,当#pragma pack的值等于或超过最长数据成员的长度的时候,
这个值的大小将不产生任何效果。 而结构整体的对齐,则按照结构体中最大的数据成员进行。
*/
struct stru1{
int b;
long c;
char a;
char d[5];
};
struct stru2{
char a;
int b;
long c;
char d[5];
};
/*
Win32下:
#pragma pack(1)的时候sizeof(stru1)=14 4+4+1+5=14
#pragma pack(2);时候:sizeof(stru1)=14 4+4+6=14
#pragma pack(4);时候sizeof(stru1)=16 4+4+8=16
#pragma pack(1)的时候sizeof(stru2)=14 1+4+4+5=14
#pragma pack(2);时候 sizeof(stru2)=16 2+4+4+6
#pragma pack(4);时候 sizeof(stru2)=20 4+4+4+8=20
*/
C++软件开发岗面试