之所以会有这样的疑问,是因为在写多线程程序的过程中经常用到vector作为序列消息的容器, 一个或多个向vector写入struct类型的元素,另外的一个或者多个线程取出元素加以处理,这也是大多数生产者消费者模型的最常用方式。在这个过程中有必要了解内存的分配和释放时机,以避免产生内存的泄漏。
typedef struct _TEST1
{
TCHAR aryt[100];
} TEST1,*LPTEST1;
在这个过程中,有以下几个问题
1.struct变量在push_back()到vector的时候,vector怎样处理呢?
答案。如果vector是一个struct类型的容器,
typedef vector <TEST1> TV;
TV tv;
TEST1 t1={0};
LPTEST1 lpt1=&t1;
memset(lpt1,'A',sizeof(TEST1)-1);
tv.push_back(t1);
memset(lpt1,'B',sizeof(TEST1)-1);
lpt2=&(tv.at(0));
TRACE("%d/n",tv.size());
TRACE("%s/n",lpt2->aryt);
在上述代码中,t1变量被push_bak到vector中,是作为值来传递的,push_back()方法会申请一块新的内存,并把t1的值(也就是数组的值)复制到新的内存缓冲区中
lpt1和tv中的元素的指针是不同的,t1,*lpt1是BBBBBBBBBBBBBBBBBB,而tv中的元素值为AAAAAAAAAAAAAAAA
2.tv.clear()之后,lpt2和lpt1是怎样的?
上述代码中lpt1指向原来的内存地址,lpt2指向的是tv的元素地址
clear()之后lpt1不受任何影响,但是tv的元素和内存都被释放,包括原的内存快被回收,此时lpt2指向的内存中的内容是不可知的,并且是危险的。
3.tv.pop_back()之后,lpt2和lpt1的情况
pop_back是用来删除最后一个元素的,当然现在只有一个元素,删除之后,该vector就变为empty,按照惯例,被移除的元素应当被释放掉,此时访问lpt2应该也是无法取得正确的值
但是实际上,我们访问lpt2发现指向的内存块中的值依然没有变化,看起来好像没有被释放掉一样,但是按照正确和严谨的原则,lpt2不应当再被访问,因为这里的释放并非还给内存堆栈,而是被vector内部保留,只是无法通过方法访问到,
我们可以再push_back(t1),按照之前说的,应该是分配一个新的内存给新的元素,但我们发现,新的元素值所在的内存地址还是lpt2指向的那一块,只是值变成了BBBBBBBB....
这个时候,我们输出lpt1->aryt和lpt2->aryt都是BBBBB......,同一块内存地址在pop_back()和push_back之后,被重复使用了,这里很奇妙,pop_back删除和clear清除,是完全不同的,可以理解为,vector内部实现的时候为了效率而做的处理。那么pop_back的元素什么时候会被完全释放,这个还需要更进一步的深入了解