关于vector的push_back()的问题

nevergiveupc 2011-10-24 10:07:36
我现在定义了一个 vector<ADAPTER*> config;
然后想给它添加元素。
就用ADAPTER * read = new ADAPTER;
然后再 config.push_back(read);
想问下现在这个new的read能否delete,经我测试是不能。
但如果不delete就会造成内存泄露。。。
大神们,给我个解决方法吧。或者讲一下原理。
...全文
285 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
yisikaipu 2011-10-26
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 chaoxuebin 的回复:]输出结果为什么会是这样啊?[/Quote]


3 2 1 是c3 c2 c1的析构
1 2 3 是容器里c1 c2 c3的拷贝的析构,这是最后清理容器时干的
push_back(c1)时,c1被拷贝了一份,扩容时,再把这个拷贝做一次拷贝。也就是说扩容时,要把容器里的元素先拿出来,然后重新放回去,只不过这里的“拿出来”,是指复制了一份,然后销毁被复制的那份
然后所有的原件和拷贝终将析构


参考下例:
#include <vector>
#include <iostream>
using namespace std;

class Cls
{
public:
Cls(int x):m(x)
{
cout <<"ctor: " <<m <<endl;
}

Cls(const Cls& c):m(c.m*10)
{
cout <<"copy: " <<m <<endl;
}

~Cls()
{
cout <<"dtor: " <<m <<endl;
}

private:
int m;
};

int main()
{
{
vector<Cls> vec;
vector<Cls*> p_vec;

Cls c1(1);
Cls c2(2);
Cls c3(3);

vec.push_back(c1);
vec.push_back(c2);
vec.push_back(c3);

Cls *p1=new Cls(4);
Cls *p2=new Cls(5);
Cls *p3=new Cls(6);

p_vec.push_back(p1);
p_vec.push_back(p2);
p_vec.push_back(p3);

for(int i=0;i<(int)p_vec.size();++i)
delete p_vec[i];
}

return 0;
}


输入如下:
ctor: 1
ctor: 2
ctor: 3
copy: 10
copy: 20
copy: 100
dtor: 10
copy: 30
copy: 1000
copy: 200
dtor: 100
dtor: 20
ctor: 4
ctor: 5
ctor: 6
dtor: 4
dtor: 5
dtor: 6
dtor: 3
dtor: 2
dtor: 1
dtor: 1000
dtor: 200
dtor: 30
请按任意键继续. . .


这里4 5 6构造,然后4 5 6析构,没有拷贝构造

所以,容器里只适合放基本类型(包括指针),小的或简单的对象
nevergiveupc 2011-10-26
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 yisikaipu 的回复:]

引用 14 楼 chaoxuebin 的回复:
我们来看看vector的增长过程。
首先开始是0,开辟一个元素的空间,放入一个对象后大小是1,然后开辟两个元素空间,复制原来的对象,再放入一个对象,销毁原来的空间(这里销毁原来的对象需要调用析构函数1次),此时大小是2。
放入两个对象需要调用拷贝构造函数2次,复制一次需要调用拷贝构造函数1次,共调用拷贝构造函数3次。
这个问题就算是解决了。……
[/Quote]

1
1
2
1000
2000
3000
3
2
1
1
2
3
输出结果为什么会是这样啊?
nevergiveupc 2011-10-26
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 yisikaipu 的回复:]
所以,容器里只适合放基本类型(包括指针),小的或简单的对象

[/Quote]
谢谢啊,学习了!
yisikaipu 2011-10-25
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 chaoxuebin 的回复:]
我们来看看vector的增长过程。
首先开始是0,开辟一个元素的空间,放入一个对象后大小是1,然后开辟两个元素空间,复制原来的对象,再放入一个对象,销毁原来的空间(这里销毁原来的对象需要调用析构函数1次),此时大小是2。
放入两个对象需要调用拷贝构造函数2次,复制一次需要调用拷贝构造函数1次,共调用拷贝构造函数3次。
这个问题就算是解决了。。。
[/Quote]



楼主,你容器里放的是指针,不是对象,容器扩容不会导致指针指向的对象析构。请看下例

#include <vector>
#include <iostream>
using namespace std;

class Cls
{
public:
Cls(int x):m(x)
{
}

~Cls()
{
cout <<m <<endl;
}

int m;
};

int main()
{
vector<Cls> vec;
vector<Cls*> p_vec;

Cls c1(1);
Cls c2(2);
Cls c3(3);

vec.push_back(c1); // 扩容,无对象可析构
vec.push_back(c2); // 扩容,c1析构
vec.push_back(c3); // 再次扩容,c1,c2析构

Cls *p1=new Cls(1000);
Cls *p2=new Cls(2000);
Cls *p3=new Cls(3000);

p_vec.push_back(p1); // 扩容,无对象可析构
p_vec.push_back(p2); // 扩容,仍无对象可析构
p_vec.push_back(p3); // 扩容,仍无对象可析构

// 在这之前,只输出1 1 2,c1,c2对象会析构
// 但指针变量p1,p2指向的对象不会被析构
// 扩容只导致指针变量被拷贝,这不影响其指向的对象

for(int i=0;i<(int)p_vec.size();++i)
delete p_vec[i];

//delete p1; // 错误,因为Cls(1000)已经delete掉

// 如果检测到内存泄露,那只是检测工具的误判

return 0;
}


再说一遍,如果检测到内存泄露,那只是检测工具的误判

当然,如果避开扩容也没什么不好,拷贝指针多少也是有开销的……
nevergiveupc 2011-10-25
  • 打赏
  • 举报
回复
我们来看看vector的增长过程。
首先开始是0,开辟一个元素的空间,放入一个对象后大小是1,然后开辟两个元素空间,复制原来的对象,再放入一个对象,销毁原来的空间(这里销毁原来的对象需要调用析构函数1次),此时大小是2。

放入两个对象需要调用拷贝构造函数2次,复制一次需要调用拷贝构造函数1次,共调用拷贝构造函数3次。
这个问题就算是解决了。。。
nevergiveupc 2011-10-25
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 yisikaipu 的回复:]

引用 10 楼 chaoxuebin 的回复:
引用 2 楼 pengzhixi 的回复:
不能delete,等vector使用完之后遍历一次进行delete

可是现在如果不delete就会造成内存泄露啊??


你认为内存泄露是什么意思?

你现在正在使用这块内存啊,这算泄露?

你程序结束前释放掉就是了

你是不是以为不把这个叫做read的指针delete掉就算内……
[/Quote]
已经明白了。如果不事先给vector分配一定的内存,即执行reserve,这个容器的容量是会自增长的,每次增加一倍。也就是之前的第一个元素会用析构函数释放掉,并重新分配内存,由于我没有写析构函数,所以造成了内存泄露。。。
ryfdizuo 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 chaoxuebin 的回复:]

引用 3 楼 lvjing_csdn 的回复:

这个在语法上可以delete,但是如果你delete掉得话就是的vector中对应的数据项成为了野指针,那么vector中的指针野就不能在使用了,必须删除掉。楼主如果怕delete掉某个read,可以这样:
config.push_back(new ADAPTER);这样所有的指针就只存储在vector中了。只要保证在删除vector中的指……
[/Quote]
config.push_back( new ADAPTER );
config.push_back( new ADAPTER );
config.push_back( new ADAPTER );
三个指针都不一样啊。。。
nevergiveupc 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 lvjing_csdn 的回复:]

这个在语法上可以delete,但是如果你delete掉得话就是的vector中对应的数据项成为了野指针,那么vector中的指针野就不能在使用了,必须删除掉。楼主如果怕delete掉某个read,可以这样:
config.push_back(new ADAPTER);这样所有的指针就只存储在vector中了。只要保证在删除vector中的指针之前delete下就可以了。
[/Quote]那如果我每添加一项,就new 同样的指针read会不会有什么问题啊?
lvjing_CSDN 2011-10-24
  • 打赏
  • 举报
回复
这个在语法上可以delete,但是如果你delete掉得话就是的vector中对应的数据项成为了野指针,那么vector中的指针野就不能在使用了,必须删除掉。楼主如果怕delete掉某个read,可以这样:
config.push_back(new ADAPTER);这样所有的指针就只存储在vector中了。只要保证在删除vector中的指针之前delete下就可以了。
pengzhixi 2011-10-24
  • 打赏
  • 举报
回复
不能delete,等vector使用完之后遍历一次进行delete
闲的每日C 2011-10-24
  • 打赏
  • 举报
回复
使用完了就delete了再从vector中remove掉这一项,就可以了啊。
yisikaipu 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 chaoxuebin 的回复:]
引用 2 楼 pengzhixi 的回复:
不能delete,等vector使用完之后遍历一次进行delete

可是现在如果不delete就会造成内存泄露啊??
[/Quote]

你认为内存泄露是什么意思?

你现在正在使用这块内存啊,这算泄露?

你程序结束前释放掉就是了

你是不是以为不把这个叫做read的指针delete掉就算内存泄露?

read只是一个指针,它所表示的那个内存地址已经被复制到vector里面,到时候用vector里那个副本去delete掉就行了

不是说你new了read,就必须delete read

比方说,
int *p=new int;
int *q=p;
delete q;
这里你把q delete掉就行了,不用也不应再去delete p;

Longerandlonger 2011-10-24
  • 打赏
  • 举报
回复
请使用share_ptr
nevergiveupc 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 pengzhixi 的回复:]

不能delete,等vector使用完之后遍历一次进行delete
[/Quote]
可是现在如果不delete就会造成内存泄露啊??
PG 2011-10-24
  • 打赏
  • 举报
回复
for(int i=0;i<vec.size();++i)
delete vec[i];
yisikaipu 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 chaoxuebin 的回复:]
那如果我每添加一项,就new 同样的指针read会不会有什么问题啊?
[/Quote]

完全没有问题
wenxibo 2011-10-24
  • 打赏
  • 举报
回复
要push 对象,而不是指针。

对象要求支持copy ,assign
nevergiveupc 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 dizuo 的回复:]

引用 4 楼 chaoxuebin 的回复:

引用 3 楼 lvjing_csdn 的回复:

这个在语法上可以delete,但是如果你delete掉得话就是的vector中对应的数据项成为了野指针,那么vector中的指针野就不能在使用了,必须删除掉。楼主如果怕delete掉某个read,可以这样:
config.push_back(new ADAPTER);这样所有的指针就只存储……
[/Quote]可是我还要先给 new ADAPTER 一些值,因为它有很多成员,并且是vector<ADAPTER*>,不能config.push_back( new ADAPTER )。。。。

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧