读书人

STL list容器的引用语议讨论,该怎么解

发布时间: 2012-03-12 12:45:33 作者: rapoo

STL list容器的引用语议讨论
前提:list中装载的引用语义(对象指针),非值语义,这里不是讨论值语义与引用语义。

请高手指点,下面的代码有没有内存问题。代码在BCB6.0中编译通过。

//---------------------------------------

#pragma hdrstop

//---------------------------------------

#include <list.h>
#include <iostream.h>
#include <algorithm.h>
#pragma argsused

const MAX_BUFFER_1 = 256;
const MAX_BUFFER_2 = 65536;

class _Parameter
{
private:
char *_name;
public:
char* __fastcall name(void) { return _name; }

__fastcall _Parameter(char* value)
{
_name = NULL;

_name = new char[strlen(value) + 1];
strcpy(_name, value);
}

__fastcall ~_Parameter()
{
std::cout < < "销毁对象: " < < _name < < std::endl;

//释放对象资料
if (_name != NULL)
delete[] _name;

}
};

template <class t> //查找函数
class findvalue
{
private:
char *_name;
public:
findvalue(char *name) : _name(name) { }
bool operator()(const t* ptr) const
{
if (strcmp(ptr-> name(), _name) == 0)
return true;
else
return false;
}
};

template <class t> //查找符合条件的容器项,并删除该项中的内容--对象指针。
class removevalue
{
private:
char *_name;
public:
removevalue(char *name) : _name(name) { }
bool operator()(const t* ptr) const
{
if (strcmp(ptr-> name(), _name) == 0)
{
delete ptr; //在此外删除对象,可行吗?
return true;


}
else
return false;
}
};

template <class t> //删除所有的指针操作。
struct deletevalue
{
void operator()(t* ptr) { delete ptr; }
};

int main(int argc, char* argv[])
{

list <_Parameter*> ::iterator iparam;
list <_Parameter*> factory;

char name[50];
_Parameter* parameter;

memset(name, '\0 ', 50);
strcpy(name, "China ");
parameter = new _Parameter(name);
factory.push_back(parameter);

memset(name, '\0 ', 50);
strcpy(name, "British ");
parameter = new _Parameter(name);
factory.push_back(parameter);

memset(name, '\0 ', 50);
strcpy(name, "America ");
parameter = new _Parameter(name);
factory.push_back(parameter);

//查找对象。
iparam = find_if(factory.begin(),
factory.end(),
findvalue <_Parameter> ( "British "));
if (iparam != factory.end())
{
cout < < "找到对象: " < <
(static_cast <_Parameter*> (*iparam))-> name() < < endl;
cout < < "对象地址: " < <
reinterpret_cast <int> (*iparam) < < endl;

}

//删除对象。
iparam = remove_if(factory.begin(),
factory.end(),
removevalue <_Parameter> ( "British "));
factory.erase(iparam);

iparam = find_if(factory.begin(),
factory.end(),
findvalue <_Parameter> ( "British "));
if (iparam == factory.end())
{
cout < < endl < < "British对象已经被删除 " < < endl < < endl;


}

//删除所有对象。
for_each(factory.begin(),
factory.end(),
deletevalue <_Parameter> ());
factory.clear();


return 0;
}
//---------------------------------------


[解决办法]
这个,我建议你不要费力自己搞了。
stl容器都有多种删除数据的方法,比如clear。。。
你还是要么使用list <boost::shared_ptr <T *> >
要么直接使用boost::ptr_list <T>
[解决办法]
有很大问题。参考《Effective》
条款33:提防在指针的容器上使用类似remove的算法
条款39:用纯函数做判断式
条款44:尽量用成员函数代替同名的算法

风格上的问题就更大了。
[解决办法]
有些问题:

1.对一个const t* 执行非const操作。

bool findvalue::operator()(const t* ptr) const
{
if (strcmp(ptr-> name(), _name) == 0) // 此处_Parameter::name是非const操作
return true;
else
return false;
}

bool removevalue::operator()(const t* ptr) const
{
if (strcmp(ptr-> name(), _name) == 0)
{
delete ptr; // 此处_Parameter::~Parameter是非const操作
// 并不能对const t*做delete
return true;
}
else
return false;
}

2. remove_if的返回值是remove操作完成后的factory.end(),
所以 factory.erase(iparam); 不必要。

将char* __fastcall _Parameter::name(void)加上const,
并将bool removevalue::operator()(const t* ptr) const 的参数改为t* ptr
LZ的用法应该可行.



[解决办法]
厄 。。。。
[解决办法]

[解决办法]
shared_ptr的问题是1直到最后一个指针delete,它才真的释放内存
2很容易发生循环引用。即使借助weaked_ptr,可以消除循环引用,可是加大了设计难度。
所以,看起来还是boost::ptr_container比较好些。
[解决办法]
很高深, 学习.
楼主的代码我没看, 写的好不好先不说, 能有精神去写就值得表扬.

读书人网 >C++

热点推荐