在C++分配内存时,如何让代码更健壮
起因
前一段时间在更新.Net Runtime源码时,发现CLR的源码我不认识的用法(毕竟是做C#的,C++的简单用法能看懂),看到nothrow的用法,便去查询了一下是怎么回事.
nothrow是在分配资源(包括内存)失败时,可以对返回的值判断并进行处理,正常这种情况下,应该使用异常处理(try catch),在没有内存可分配时,使用异常处理也无济于事.
在C语言中,分配资源时
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
char* str = (char*)malloc(sizeof(char) * 128);
if (str == NULL) //如果str指向NULL,代表分配内存失败
{
printf("申请内存失败,没有可用的内存");
exit(1);
}
return 0;
}
在C++ 分配资源使用nothrow
#include <iostream>
using namespace std;
class Person
{
public:
Person()
{
cout << "构造函数" << endl;
}
~Person()
{
cout << "析构函数" << endl;
}
static void* operator new (size_t size)
{
cout << "局部 new " << endl;
Person* p = ::new Person; //引用全局的new,这里还是会调用一次构造函数
return p;
}
static void operator delete(void* p)
{
cout << "局部 delete " << endl;
::delete p;
}
};
int main(int argc, char* argv[])
{
Person* p1 = ::new(std::nothrow) Person;
if (!p1) //在分配资源后,判断资源是否分配成功
{
cout << "申请内存失败,没有可用的内存" << endl;
exit(1);
}
return 0;
}
nothrow在标准库下,nothrow是一个结构体.具体可以看文档:operator new
//这是使用VS转定义查看的
#ifndef __NOTHROW_T_DEFINED
#define __NOTHROW_T_DEFINED
namespace std
{
struct nothrow_t {
explicit nothrow_t() = default;
};
#ifdef _CRT_ENABLE_SELECTANY_NOTHROW
extern __declspec(selectany) nothrow_t const nothrow;
#else
extern nothrow_t const nothrow;
#endif
}
#endif
在@0xc0000082(头条号)的帮助下,看到在new的时候加上nothrow,只是调用new带nothrow的重载方法.
//默认调用new
_NODISCARD _Ret_notnull_ _Post_writable_byte_size_(_Size) _VCRT_ALLOCATOR
void* __CRTDECL operator new(
size_t _Size
);
//加nothrow的new重载 noexcept等同noexcept(true),不抛出异常
_NODISCARD _Ret_maybenull_ _Success_(return != NULL) _Post_writable_byte_size_(_Size) _VCRT_ALLOCATOR
void* __CRTDECL operator new(
size_t _Size,
::std::nothrow_t const&
) noexcept;
秋风
2021-09-13