c++ 资源回收学习
使用 delete
这样的 delete
基本回收资源操作,容易遗忘,或者是在函数中由于其他原因在中途出现异常或者被其他人 return
返回操作,如下
```
#include <iostream>
void demo1(int a1)
{
int* tmpi = new int;
*tmpi = a1;
if (*tmpi == 1)
{
return;
}
std::cout << *tmpi << "\n";
delete tmpi;
}
int main()
{
demo1(0); // 正常释放
demo1(1); // 没有释放
}
```
怎么防止这种没有正常释放资源操作
-
使用 class
封装,c++ 的析构函数,在对象消亡时即自动被调用。
#include <iostream>
using namespace std;
class Test {
public:
Test() {
tmpi = new int;
};
~Test() {
if (tmpi)
{
std::cout << "delete tmpi;" << "\n";
delete tmpi;
}
};
void demo1(int a1) {
*tmpi = a1;
if (*tmpi == 1)
{
return;
}
std::cout << *tmpi << "\n";
};
private:
int* tmpi = nullptr;
};
int main()
{
Test t1;
t1.demo1(0);
t1.demo1(1);
}
0
delete tmpi;
-
使用 智能指针
#include <iostream>
#include <memory>
using namespace std;
int main()
{
// shared_ptr<int> tmpi_1(new int);
// shared_ptr<int> tmpi_1 = make_shared<int>(new int);
int* check_tmpi_2 = nullptr;
{
shared_ptr<int> tmpi_2(new int);
*tmpi_2 = 2;
// 获取 shared_ptr 托管的资源
check_tmpi_2 = tmpi_2.get();
std::cout << "tmpi_2:" << *tmpi_2 << "\n";
std::cout << "check_tmpi_2:" << *check_tmpi_2 << "\n";
// 出了作用域 释放掉托管的 tmpi_2
}
std::cout << "释放 check_tmpi_2:" << *check_tmpi_2 << "\n";
int* tmpi_1 = new int;
*tmpi_1 = 1;
{
shared_ptr<int> tmpi_ptr(tmpi_1);
// 出了作用域 释放掉托管的 tmpi_1
}
std::cout << "释放 tmpi_1:" << *tmpi_1 << "\n"; // 输出 乱码,已经释放掉
}
-
使用 lambda, 委托其他类回收, 这种方式更过适用于 closefandle(client);
来回收资源的方式,[参考](http://mindhacks.cn/2012/08/27/modern-cpp-practices/)
#include <iostream>
#include <memory>
using namespace std;
// --beg ScopeGuard
#include <functional>
class ScopeGuard
{
public:
explicit ScopeGuard(std::function<void()> onExitScope)
: onExitScope_(onExitScope), dismissed_(false)
{ }
~ScopeGuard()
{
if (!dismissed_)
{
onExitScope_();
}
}
void Dismiss()
{
dismissed_ = true;
}
private:
std::function<void()> onExitScope_;
bool dismissed_;
private: // noncopyable
ScopeGuard(ScopeGuard const&);
ScopeGuard& operator=(ScopeGuard const&);
};
#define SCOPEGUARD_LINENAME_CAT(name, line) name##line
#define SCOPEGUARD_LINENAME(name, line) SCOPEGUARD_LINENAME_CAT(name, line)
#define ON_SCOPE_EXIT(callback) ScopeGuard SCOPEGUARD_LINENAME(EXIT, __LINE__)(callback)
// -- end ScopeGuard
int main()
{
int *tmp = new int;
ScopeGuard exitG([&] {
if (tmp)
{
std::cout << "delete tmp" << endl;
delete tmp;
}
});
*tmp = 2;
std::cout << "*tmp =" << *tmp << endl;
}
-
windows 使用 socket 例子
#include <iostream>
#include <memory>
// --beg ScopeGuard
#include <functional>
class ScopeGuard
{
public:
explicit ScopeGuard(std::function<void()> onExitScope)
: onExitScope_(onExitScope), dismissed_(false)
{ }
~ScopeGuard()
{
if (!dismissed_)
{
onExitScope_();
}
}
void Dismiss()
{
dismissed_ = true;
}
private:
std::function<void()> onExitScope_;
bool dismissed_;
private: // noncopyable
ScopeGuard(ScopeGuard const&);
ScopeGuard& operator=(ScopeGuard const&);
};
#define SCOPEGUARD_LINENAME_CAT(name, line) name##line
#define SCOPEGUARD_LINENAME(name, line) SCOPEGUARD_LINENAME_CAT(name, line)
#define ON_SCOPE_EXIT(callback) ScopeGuard SCOPEGUARD_LINENAME(EXIT, __LINE__)(callback)
// -- end ScopeGuard
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
int main()
{
WORD sockVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(sockVersion, &wsaData) != 0)
{
return 0;
}
//创建套接字
SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (slisten == INVALID_SOCKET)
{
printf("socket error !");
return 0;
}
// ON_SCOPE_EXIT 释放资源
ScopeGuard exitG([&] {
printf("\n ON_SCOPE_EXIT 释放资源 ! \n");
closesocket(slisten);
WSACleanup();
});
// 或者 ON_SCOPE_EXIT
// ON_SCOPE_EXIT([&] {
// printf("\n ON_SCOPE_EXIT 释放资源 ! \n");
// //std::cout << "ON_SCOPE_EXIT" << "\n";
// closesocket(slisten);
// WSACleanup();
// });
//绑定IP和端口
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(10010);
sin.sin_addr.S_un.S_addr = INADDR_ANY;
if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
{
printf("bind error !");
}
//开始监听
if (listen(slisten, 5) == SOCKET_ERROR)
{
printf("listen error !");
return 0;
}
SOCKET sClient;
sockaddr_in remoteAddr;
int nAddrlen = sizeof(remoteAddr);
char revData[255];
while (true)
{
printf("wait...\n");
sClient = accept(slisten, (SOCKADDR*)&remoteAddr, &nAddrlen);
if (sClient == INVALID_SOCKET)
{
printf("accept error !");
continue;
}
printf("new connect:%d.%d.%d.%d:%d \r\n", remoteAddr.sin_addr.S_un.S_un_b.s_b1, remoteAddr.sin_addr.S_un.S_un_b.s_b2, remoteAddr.sin_addr.S_un.S_un_b.s_b3, remoteAddr.sin_addr.S_un.S_un_b.s_b4, remoteAddr.sin_port);
//接收数据
int ret = recv(sClient, revData, 255, 0);
if (ret > 0)
{
revData[ret] = 0x00;
printf(revData);
}
//发送数据
const char* sendData = "tcp server bak!\n";
send(sClient, sendData, strlen(sendData), 0);
closesocket(sClient);
break;
}
}
wait...
new connect:127.0.0.1:60155
testes send from client
ON_SCOPE_EXIT 释放资源 !
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)