
假设您遇到这样的问题,有一个部落,有几个成员,每个成员有两个属性,分别是年龄和状态级别. 为了在程序中构造这样的部落对象,您将想到一种嵌套结构的方式. 众所周知,部落成员不是固定的,我们使用指针来表示成员.
因此calloc 释放,现在有两个结构,第二个结构嵌套在第一个结构中. 如何分配和管理动态内存?本文是这种类型的结构的内存管理的实践.
首先构造第一个结构,假设内部结构为INSIDE,并赋予属性a和b,则结构代码如下:
typedef struct _stuInside
{
int a;
int b;
} INSIDE;
然后构造第二个结构,假设外部结构为OUTSIDE,因为成员的数量是动态的,所以我们构造一个变量而不是结构中的数量,然后使用内部结构指针来表示元素集,结构代码如下:
typedef struct _stuOutside
{
int count;
INSIDE *element;
} OUTSIDE;

数据结构构建完成. 接下来,为了使用此数据结构,我们需要创建其对象,但是如上面的代码所示,此结构不为成员分配内存,也就是说,它需要为该结构动态分配内存. 总之,有以下几种情况:
1,一个部落成员
2. 一个部落的多个成员
3. 多个部落的一名成员
4. 来自多个部落的多个成员
代码摘要,即

OUTSIDE *p = new OUTSIDE; OUTSIDE *p = new (n) OUTSIDE; OUTSIDE *p = new OUTSIDE[n]; OUTSIDE *p = new (n) OUTSIDE[n];
从上面的代码中可以看到,我选择了分配内存空间的新方法. 没有问题很简单,但是要仔细考虑,这是有问题的,因为外部结构的第二个成员是一个指针,新分配给该成员的内存空间大小为4个字节.
要解决此问题,我选择的方法是对此结构重载新的运算符. 为什么不重载它,而不是直接在用户代码中分配它. 我的理由是calloc 释放,由于此数据结构是抽象的通用结构,因此它被非常频繁地调用,因此期望将复杂的内存分配给调用者来实现,最好直接封装到该结构本身中,这样可以减轻调用者的负担关于内存管理.
从以上代码还可以看出,这里需要重载的新运算符是new运算符,new运算符(n),operator new [],operator new(n)[]和in中的new运算符. 标准C ++它实际上是一个函数,其形式为void * operatornew(size_t大小). 我不会介绍这部分知识. 在Internet上查找信息很容易.
我的重新加载代码:
static void * operator new(size_t size)
{
// 用标准new处理size错误,含size=0
if (size != sizeof(struct _stuOutside))
{
return ::operator new(size);
}
while (1) // 无限循环处理
{
void *p = malloc(size);
if (p != 0)
{
struct _stuOutside *pp = (struct _stuOutside *)p;
pp->count = 1;
pp->element = (INSIDE *)malloc(sizeof(INSIDE));
return p; // 分配成功后返回指针
}
new_handler curhandler = set_new_handler(0);
set_new_handler(curhandler);
if (curhandler != 0)
(*curhandler)();
else
throw std::bad_alloc();
}
}
static void * operator new[] (size_t size)
{
// 用标准new处理size错误,含size=0
if ((size == 0) || (size%sizeof(struct _stuOutside) != 0))
{
return ::operator new(size);
}
while (1) // 无限循环处理
{
void *p = malloc(size);
if (p != 0)
{
int cnt = size/sizeof(struct _stuOutside);
for (int i=0;i<cnt;i++)
{
struct _stuOutside *pp = (struct _stuOutside *)p + i;
pp->count = 1;
pp->element = (INSIDE *)malloc(sizeof(INSIDE));
}
return p; // 分配成功后返回指针
}
new_handler curhandler = set_new_handler(0);
set_new_handler(curhandler);
if (curhandler != 0)
(*curhandler)();
else
throw std::bad_alloc();
}
}
static void * operator new(size_t size, const int x)
{
// 用标准new处理size错误,含size=0
if (size != sizeof(struct _stuOutside))
{
return ::operator new(size);
}
while (1) // 无限循环处理
{
void *p = malloc(size);
if (p != 0)
{
struct _stuOutside *pp = (struct _stuOutside *)p;
pp->count = x;
pp->element = (INSIDE *)malloc(x * sizeof(INSIDE));
return p; // 分配成功后返回指针
}
new_handler curhandler = set_new_handler(0);
set_new_handler(curhandler);
if (curhandler != 0)
(*curhandler)();
else
throw std::bad_alloc();
}
}
static void * operator new[] (size_t size, const int x)
{
// 用标准new处理size错误,含size=0
if ((size == 0) || (size%sizeof(struct _stuOutside) != 0))
{
return ::operator new(size);
}
while (1) // 无限循环处理
{
void *p = malloc(size);
if (p != 0)
{
int cnt = size/sizeof(struct _stuOutside);
for (int i=0;i<cnt;i++)
{
struct _stuOutside *pp = (struct _stuOutside *)p + i;
pp->count = x;
pp->element = (INSIDE *)malloc(x * sizeof(INSIDE));
}
return p; // 分配成功后返回指针
}
new_handler curhandler = set_new_handler(0);
set_new_handler(curhandler);
if (curhandler != 0)
(*curhandler)();
else
throw std::bad_alloc();
}
}

上面的代码比较简单,我的知识在这里提供了一个想法,我将不对其进行详细阐述,有兴趣的朋友可以留言与我交流. 唯一值得注意的是,最好处理内存分配异常处理,很多朋友会忽略
new_handler curhandler = set_new_handler(0); set_new_handler(curhandler); if (curhandler != 0) (*curhandler)(); else throw std::bad_alloc();尽管在通常情况下,程序不是存在问题,但是一旦发生异常,就会非常麻烦,尤其是对于调用方来说,解决问题的压力更大.
以下是我编写的完整测试代码:
// testStructMemeryAllocate.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <new>
#include <iostream>
using namespace std;
typedef struct _stuInside
{
int a;
int b;
} INSIDE;
typedef struct _stuOutside
{
int count;
INSIDE *element;
//////////////////////////////////////////////////////////////////////////
// new - delete
static void * operator new(size_t size)
{
// 用标准new处理size错误,含size=0
if (size != sizeof(struct _stuOutside))
{
return ::operator new(size);
}
while (1) // 无限循环处理
{
void *p = malloc(size);
if (p != 0)
{
struct _stuOutside *pp = (struct _stuOutside *)p;
pp->count = 1;
pp->element = (INSIDE *)malloc(sizeof(INSIDE));
return p; // 分配成功后返回指针
}
new_handler curhandler = set_new_handler(0);
set_new_handler(curhandler);
if (curhandler != 0)
(*curhandler)();
else
throw std::bad_alloc();
}
}
static void * operator new[] (size_t size)
{
// 用标准new处理size错误,含size=0
if ((size == 0) || (size%sizeof(struct _stuOutside) != 0))
{
return ::operator new(size);
}
while (1) // 无限循环处理
{
void *p = malloc(size);
if (p != 0)
{
int cnt = size/sizeof(struct _stuOutside);
for (int i=0;i<cnt;i++)
{
struct _stuOutside *pp = (struct _stuOutside *)p + i;
pp->count = 1;
pp->element = (INSIDE *)malloc(sizeof(INSIDE));
}
return p; // 分配成功后返回指针
}
new_handler curhandler = set_new_handler(0);
set_new_handler(curhandler);
if (curhandler != 0)
(*curhandler)();
else
throw std::bad_alloc();
}
}
static void * operator new(size_t size, const int x)
{
// 用标准new处理size错误,含size=0
if (size != sizeof(struct _stuOutside))
{
return ::operator new(size);
}
while (1) // 无限循环处理
{
void *p = malloc(size);
if (p != 0)
{
struct _stuOutside *pp = (struct _stuOutside *)p;
pp->count = x;
pp->element = (INSIDE *)malloc(x * sizeof(INSIDE));
return p; // 分配成功后返回指针
}
new_handler curhandler = set_new_handler(0);
set_new_handler(curhandler);
if (curhandler != 0)
(*curhandler)();
else
throw std::bad_alloc();
}
}
static void * operator new[] (size_t size, const int x)
{
// 用标准new处理size错误,含size=0
if ((size == 0) || (size%sizeof(struct _stuOutside) != 0))
{
return ::operator new(size);
}
while (1) // 无限循环处理
{
void *p = malloc(size);
if (p != 0)
{
int cnt = size/sizeof(struct _stuOutside);
for (int i=0;i<cnt;i++)
{
struct _stuOutside *pp = (struct _stuOutside *)p + i;
pp->count = x;
pp->element = (INSIDE *)malloc(x * sizeof(INSIDE));
}
return p; // 分配成功后返回指针
}
new_handler curhandler = set_new_handler(0);
set_new_handler(curhandler);
if (curhandler != 0)
(*curhandler)();
else
throw std::bad_alloc();
}
}
static void operator delete(void *p)
{
if (p == 0) // 检查空指针
{
return ;
}
struct _stuOutside *pp = (struct _stuOutside *)p;
if (pp->element != 0)
{
free(pp->element); // 释放成员内存
}
free(p); // 释放自身内存
}
// 释放数组内存时,要求必须先调用delete[]对每个元素进行释放,然后再调用delete对整体数组释放
static void operator delete[] (void *p)
{
if (p == 0) // 检查空指针
{
return ;
}
struct _stuOutside *pp = (struct _stuOutside *)p;
if (pp->element != 0)
{
free(pp->element); // 释放成员内存
pp->count = 0;
pp->element = 0;
}
}
} OUTSIDE;
int _tmain(int argc, _TCHAR* argv[])
{
//////////////////////////////////////////////////////////////////////////
cout<<"test new"<<endl;
OUTSIDE *p1 = new OUTSIDE;
cout<<p1->count<<endl;
INSIDE t;
t.a = 0;
t.b = 9;
p1->element[0] = t;
for (int i=0;i<p1->count;i++)
{
cout<<p1->element[i].a<<":"<<p1->element[i].b<<endl;
}
delete p1;
cout<<endl;
//////////////////////////////////////////////////////////////////////////
cout<<"test new(x)"<<endl;
OUTSIDE *p2 = new (2) OUTSIDE;
cout<<p2->count<<endl;
INSIDE t1,t2;
t1.a = 1;
t1.b = 11;
t2.a = 2;
t2.b = 22;
p2->element[0] = t1;
p2->element[1] = t2;
for (int i=0;i<p2->count;i++)
{
cout<<p2->element[i].a<<":"<<p2->element[i].b<<endl;
}
delete p2;
cout<<endl;
//////////////////////////////////////////////////////////////////////////
cout<<"test new[]"<<endl;
OUTSIDE *p3 = new OUTSIDE[2];
cout<<"0:"<<p3[0].count<<endl;
cout<<"1:"<<p3[1].count<<endl;
INSIDE t3,t4;
t3.a = 3;
t3.b = 33;
t4.a = 4;
t4.b = 44;
p3[0].element[0] = t3;
p3[1].element[0] = t4;
for (int j=0;j<2;j++)
{
for (int i=0;i<p3[j].count;i++)
{
cout<<j<<":"<<p3[j].element[i].a<<":"<<p3[j].element[i].b<<endl;
}
}
delete []p3;
delete [](p3+1);
delete p3;
cout<<endl;
//////////////////////////////////////////////////////////////////////////
cout<<"test (x)new[]"<<endl;
OUTSIDE *p4 = new (2)OUTSIDE[2];
cout<<"0:"<<p4[0].count<<endl;
cout<<"1:"<<p4[1].count<<endl;
INSIDE t5,t6,t7,t8;
t5.a = 5;
t5.b = 55;
t6.a = 6;
t6.b = 66;
t7.a = 7;
t7.b = 77;
t8.a = 8;
t8.b = 88;
p4[0].element[0] = t5;
p4[0].element[1] = t6;
p4[1].element[0] = t7;
p4[1].element[1] = t8;
for (int j=0;j<2;j++)
{
for (int i=0;i<p4[j].count;i++)
{
cout<<j<<":"<<p4[j].element[i].a<<":"<<p4[j].element[i].b<<endl;
}
}
delete []p4;
delete [](p4+1);
delete p4;
cout<<endl;
//////////////////////////////////////////////////////////////////////////
cout<<"the end !"<<endl;
return 0;
}
结果如下:

在调试过程中监视内存的分配和释放,如下所示:
分配内存使用后,内存状况:
用尽后,释放内存后,内存状况:
从图中可以看出,内存的释放是正常的,并且没有遗漏,尽管成员的内存地址不是通用数组那样的连续地址. 这样可以确保调用方调用的数据结构是内存安全的.

释放与c ++结构相关的内存
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-165531-1.html
结果大家认为捡垃圾的马云说的是屁话