关于指针vector的问题

imfjl 2003-01-08 03:14:05
如果声明一个类指针的vector.即vector的元素是类的指针,当插入多个元素后,执行clear时,会不会自动调用类指针的析构函数?
若自己手工遍历vector,删除各元素时,用如下语句
delete(*it)//it是其iterator;
或者
delete((A*)(*it))//A是类名
此两种方法有什么不同呢?
...全文
1929 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
liu_feng_fly 2003-03-12
  • 打赏
  • 举报
回复
to merlinran(天行者) :
我觉得他们说的就是智能指针,《c++沉思录》里面叫handle吧,其实际还是一个智能指针,和auto_ptr counted_ptr之类的东西差不多,只不过用一个类封装了一下,在模仿指针的功能,再增加一些安全防范措施而已。和我前面说的如果直接放对象就无法体现多态差距远已。
如果要使用这些智能指针,那么,在stl里面只有auto_ptr这一种智能指针。可是无法把他放到容器里面,有所有权转移的问题。其他的象counted_ptr shared_ptr都是其他库里面的东西,还没有标准化。是否要用,就见仁见智了。而且,你的编译器是否支持那些库也是一个问题。如果自己写,噢,写一个优秀的智能指针模板类可不是意见容易的事情,呵呵。
你可以看看今年的《程序员》第一期,有一个是c++之父的访谈录。当问到这个问题的时候,B.S.的回答就是在vector里面放指针
xkak2 2003-03-11
  • 打赏
  • 举报
回复
谁说在vector存放指针不对?看看《c++ primer》里的介绍吧,如果你的类很大,最好存放指针,否则vector<A>会效率很低。因为vector会调用拷贝构造函数拷贝一份副本。
如果存放的是指针,你必须在把该指针移出vector时自己释放它指向的内存。
小心在vector里使用auto_ptr,否则可能出现难以预料的问题。大家自己跟踪一下vector和auto_ptr就知道了。
merlinran 2003-03-11
  • 打赏
  • 举报
回复
liu_feng_fly(笑看风云 搏击苍穹 衔日月)

[[[如果放具体的对象,那么运行时多态就无法体现了。只有放指针,虚函数这样的机制才会起作用]]]

在不久以前,我也为之烦恼。但在新帆新闻组一位老大的解释之后,恍然大悟。下面是他的一部分回复,另外《C++沉思录》对此有更深刻和详细的描述。

------------------------------
和有些语言不同,C++ 里的对象模型需要 DIY,因此有一定的难度。

最常用的两种拷贝语义就是“值”语义和“多态对象”语义,后者在其他语言里也叫“引用”语义。“值”类型的使用相对要简单的多。

可以用聪明指针把“多态对象”类型包装成“值”语义的类型。

一般对多态的对象类型重载操作符没有多大意义。

在设计一个类时,尽量让它的语义极端化,这样该实现的操作和用法就会变得自然而明显。
------------------------------
Song 2003-03-11
  • 打赏
  • 举报
回复
我最近就经常用这个vector,以下是我的点点经验
clear()一定不会调用析构函数,只是把vector清空而已,所以在如果想清除vector,一定要先delete
可以这样:
int size=vector.size();
for(i=0;i<size;i++)
{
delete vector[i];
vector.erase(&vector[i]); //对于是存放类指针的vector,得这样做
}
wingfiring 2003-03-11
  • 打赏
  • 举报
回复
谁说vector不能自动析构?自己提供一个allocator就可以了。allocator提供allocate,deallocate,destroy,max_size,construct等一些方法,供容器使用。这样,你就可以使用指针,而让容器自动去释放资源。
夜雨悠扬 2003-02-25
  • 打赏
  • 举报
回复
vector 只是一种容器,他没有自动析构其元素的功能,所以必须在外部析构
你说的两种方法都可以
Zhayinghua 2003-02-24
  • 打赏
  • 举报
回复
一定要删除,否则会内存泄漏,可以这样实现:
class A;
class B
{
B();
virtual ~B();
vacotr<A*> a;
}

B::~B()
{
for(a::itorater i = a.begin(); i!= a.end(); ++i)
delete (*i);
a.clear();
}
ToUpdate 2003-01-14
  • 打赏
  • 举报
回复
up
topikachu 2003-01-13
  • 打赏
  • 举报
回复
如果这个指针没有副本,那么在释放vector之前手工释放所有的指针
如果这个指针有副本,呵呵 自己看着办吧:)
liu_feng_fly 2003-01-13
  • 打赏
  • 举报
回复
to singlerace:
如果放具体的对象,那么运行时多态就无法体现了。只有放指针,虚函数这样的机制才会起作用
frankxht 2003-01-13
  • 打赏
  • 举报
回复
完全同意楼上的看法。
遍历删除。
wincf 2003-01-13
  • 打赏
  • 举报
回复
1.clear() 不调用析构函数
2.delete *it 调用析构函数
可用以下程序测试出来:

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

ofstream txtout("test.txt");

class A
{
public:
A(){
txtout<<"A constructor!"<<endl;
}
virtual ~A();
};
A::~A(){
txtout<<"A destructor!"<<endl;
}

const int test_size = 10;
void main()
{
{
vector< A * > the_vector,the_vector_copy;
A * pa;

for ( int i=0; i<test_size; i++ )
{
pa = new A();
the_vector.push_back(pa);
the_vector_copy.push_back(pa);
}

txtout<<endl;
txtout<<"before delete..."<<endl;
pa = the_vector[0];
delete pa;
txtout<<"after delete..."<<endl;
txtout<<endl;

txtout<<endl;
txtout<<"before clear..."<<endl;
the_vector.clear();
txtout<<"after clear..."<<endl;
txtout<<endl;

txtout<<endl;
txtout<<"before all deleting..."<<endl;
for ( i=1; i<test_size; i++ )
delete the_vector_copy[i];
}
txtout<<"after all deleting..."<<endl;
txtout<<endl;
}

test.txt内容如下:
A constructor!
A constructor!
A constructor!
A constructor!
A constructor!
A constructor!
A constructor!
A constructor!
A constructor!
A constructor!

before delete...
A destructor!
after delete...


before clear...
after clear...


before all deleting...
A destructor!
A destructor!
A destructor!
A destructor!
A destructor!
A destructor!
A destructor!
A destructor!
A destructor!
after all deleting...

atma 2003-01-13
  • 打赏
  • 举报
回复
1.clear不会帮你调到你的析构函数的.
2.如果你定义的时候是vector<A*>,那么delete(*it) 和 delete((A*)(*it))是一样的.
否则,delete(*it)的行为不确定.如果你定义的时候是这样的:vector<void*>,那么你释放的仅仅是你对象的空间.如果你的对象中还有指向其他内存区域的指针,那就不会被释放.就会发生内存泄漏.
singlerace 2003-01-12
  • 打赏
  • 举报
回复
一般来说在vector存放对象指针是多此一举,使用vector<A>不是更好吗
J2eeLearner 2003-01-10
  • 打赏
  • 举报
回复
我给你的是STL里面的源码中的一段:
class vector
{
void clear() { erase(begin(), end()); }

iterator erase(iterator __first, iterator __last) {
iterator __i = copy(__last, _M_finish, __first);
destroy(__i, _M_finish);
_M_finish = _M_finish - (__last - __first);
return __first;
}
}
可见,vector::clear()所做的仅仅是对里面的元素调用析构函数!
而你的元素是指针,那么也就是等于什么都不做!
所以如果你想要释放指针所指向的内容,必须自己完成。

这时候你可以有两种选择:
1) 用smart pointer作为元素,对原来的指针做一个封装。但是会有其他的问题,smart pointer is unassignable . 那么就改成counted pointer吧!
2) 还是用普通的指针作为元素,这样就是你自己负责容器内部指针所指向的内存的操作,也就有了“那块内存是否为堆内存”的讨论。如果不是堆内存(不是new出来的),那么你delete就危险;如果是对内存,你还需要保证那个class object的析构函数是虚函数!
3) 为了保证简单性,你可以要求你的class必须是堆对象(可以参考More Effective c++),让构造函数为protected,另外定一个createobject()成员方法!
widewave 2003-01-08
  • 打赏
  • 举报
回复
直接用
delete(*it);
好了。
干吗要转化一下?多此一举,并且就如liu_feng_fly(笑看风云 搏击苍穹 衔日月) 所说,还多了假设条件。
imfjl 2003-01-08
  • 打赏
  • 举报
回复
怎么办呢???
imfjl 2003-01-08
  • 打赏
  • 举报
回复
什么意思?我每次都是new出一个新的对象,然后把指针放到vector里面去的,而且该类没有任何基类以及子类的.
一般,如果大家要放进vector里的是指针的话,如果释放内存的呢?
WangHz 2003-01-08
  • 打赏
  • 举报
回复
up
liu_feng_fly 2003-01-08
  • 打赏
  • 举报
回复
to imfjl
你要确保,
如果class A属于某个类的继承体系的基类,那么它应该有一个虚的析构函数。
如果你放到vector里面的指针不是new的class A的指针,并且class A不属于任何一个类的继承体系,那么你这样做的结果未定义
加载更多回复(4)

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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