为了高效
# 为了高效
Owner: -QVQ-
# RAII惯用法
goto语句、while(0) + break语句都能实现避免重复的资源释放语句
RAII:资源在拿到时就初始化好了,不需要资源时可以自动释放
class ServerSocket
{
public:
ServerSocket()
{
m_bInit = false;
m_ListenSocket = -1;
}
~ServerSocket(){//析构的时候自动释放资源
if (m_ListenSocket != -1)
::closesocket(m_ListenSocket);//调用外部的处理函数
if (m_bInit)
::WSACleanup();
}
bool DoInit()
{
……
}
}
int main(){
ServerSocket serverSocket;//不在构造函数中初始化
if (!serverSocket.DoInit())//单独用函数初始化,再判断执行状态
return false;//当初始化失败时,退出函数执行,从而调用析构函数释放资源
if (!serverSocket.DoBind("0.0.0.0", 6000))
return false;
if (!serverSocket.DoListen(15))
return false;
if (!serverSocket.DoAccept())
return false;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# pimpl惯用法
当一个组件提供给其他人使用时往往需要递交头文件,为了不在头文件里暴露太多实现细节,可以将一些私有变量封装成一个类中类
通常:
class CSocketClient
{
public:
CSocketClient();
~CSocketClient();
public:
void SetProxyWnd(HWND hProxyWnd);
private:
SOCKET m_hSocket;
short m_nPort;
char m_szServer[64];
long m_nLastDataTime; //最近一次收发数据的时间
long m_nHeartbeatInterval; //心跳包时间间隔,单位秒
CRITICAL_SECTION m_csLastDataTime; //保护m_nLastDataTime的互斥体
HANDLE m_hSendDataThread; //发送数据线程
HANDLE m_hRecvDataThread; //接收数据线程
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
调整后:头文件中声明Impl类,cpp中实现
/*************.h文件**************/
class CSocketClient
{
public:
CSocketClient();
~CSocketClient();
public:
void SetProxyWnd(HWND hProxyWnd);
private:
class Impl;//类声明,因为这个类只有这个类使用,因此在类内定义
Impl* m_pImpl;//封装的私有变量
//更进一步,使用智能指针
//std::unique_ptr<Impl> m_pImpl;
};
/*************.cpp文件**************/
CSocketClient::CSocketClient(){
m_pImpl = new Impl();
}
CSocketClient::~CSocketClient(){
delete m_pImpl;
}
void CSocketClient::SetProxyWnd(HWND hProxyWnd){
}
//辅助类,也可以用struct
//因为在.cpp里定义的,因此其他文件包含.h时,不能直接访问这个类
class CSocketClient::Impl{
public:
Impl()
{
//TODO: 你可以在这里对成员变量做一些初始化工作
}
~Impl()
{
//TODO: 你可以在这里做一些清理工作
}
public:
SOCKET m_hSocket;
short m_nPort;
char m_szServer[64];
long m_nLastDataTime; //最近一次收发数据的时间
long m_nHeartbeatInterval; //心跳包时间间隔,单位秒
CRITICAL_SECTION m_csLastDataTime; //保护m_nLastDataTime的互斥体
HANDLE m_hSendDataThread; //发送数据线程
HANDLE m_hRecvDataThread; //接收数据线程
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# vector实现统一管理局部、线程
为了实现深拷贝的方式给map赋值
map<string, stu> maps;
auto& k = maps["h"];
sheng_copy(stus, k);//这个函数内,将stus类里的内容深拷贝给maps["h"]
1
2
3
2
3
用vevtor+智能指针管理句柄
vector<shared_ptr<handle>> clis;
for(int i = 0; i < thread; i++{
handle* han = create_handle();
if(handle_open(han)==-1){};
clis.emplace_back(han, [](handle *han){
handle_close(han);
handle_destory(han);
});
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
用vector+线程管理线程
vector<thread> thrs;
for(int i = 0; i < threads; i++){
thrs.emplace_back([&](){
function_a();
});
}
for(auto &i : thrs){
i.join();
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
闭包实现自定义set的管理
class stu{
std::set<std::pair<int,int>,
std::function<bool(const std::pair<int,int> a,
const std::pair<int,int> b)>> peer;
stu():peer([](const std::pair<int,int>&a, const std::pair<int,int>&b){
return a.first==b.first;
}){
}
};
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
上次更新: 2025/02/21, 14:57:10