C+;中带字符串键的查找表的内存管理+; 我在C++中实现了一个双关键字(int和string)查找表,想知道如何编写一个析构函数。
lookup table API允许用户在表中插入和查找命名对象。在封面下,将自动为保存对象名称的字符串指定一个唯一的int键。插入后,可以通过其字符串名称或int值查找插入的对象 以下是实施的要点C+;中带字符串键的查找表的内存管理+; 我在C++中实现了一个双关键字(int和string)查找表,想知道如何编写一个析构函数。,c++,string,memory-management,C++,String,Memory Management,lookup table API允许用户在表中插入和查找命名对象。在封面下,将自动为保存对象名称的字符串指定一个唯一的int键。插入后,可以通过其字符串名称或int值查找插入的对象 以下是实施的要点 template <class VALUE> class COLLECTION { public; typedef int IDX; typedef std::map< std::string , IDX > NAME_TO_IDX; ty
template <class VALUE>
class COLLECTION
{
public;
typedef int IDX;
typedef std::map< std::string , IDX > NAME_TO_IDX;
typedef std::map< IDX, std::string > IDX_TO_NAME;
typedef std::map<IDX, VALUE*> IDX_TO_VAL;
...
void insert( const std::string name, VALUE* v )
{
m_name_to_idx_map[name] = m_next_idx;
m_idx_to_name_map[m_next_idx] = name;
m_idx_to_val_map[m_next_idx] = v;
++m_next_idx;
}
VALUE* get_value( const IDX idx ) { return m_idx_to_val_map[idx]; }
VALUE* get_value( const std::string name )
....
private:
int m_next_idx;
NAME_TO_IDX m_name_to_idx_map;
IDX_TO_NAME m_idx_to_name_map;
IDX_TO_VAL m_idx_to_val_map;
模板
类集合
{
公众;
typedef int-IDX;
typedef std::mapNAME_TO_IDX;
typedef std::mapIDX_TO_NAME;
typedef std::将IDX_映射到_VAL;
...
void insert(常量std::字符串名称,值*v)
{
m_name_to_idx_map[name]=m_next_idx;
m_idx_to_name_map[m_next_idx]=名称;
m_idx_to_val_map[m_next_idx]=v;
++m_next_idx;
}
VALUE*get_VALUE(const IDX IDX){return m_IDX_to_val_map[IDX];}
值*获取值(常量标准::字符串名称)
....
私人:
int m_next_idx;
NAME_TO_IDX m_NAME_TO_IDX_map;
IDX_TO_NAME m_IDX_TO_NAME_map;
IDX_至_VAL m_IDX_至_VAL_地图;
如何为这个类编写析构函数?
谢谢堆分配的唯一部分可能是VALUE*(不太支持大写)。 对于析构函数,必须循环遍历映射并删除所有相关指针,如下所示
for(auto iter = IDX_TO_VAL.begin(); iter != IDX_TO_VAL.end(); ++iter)
{
delete (*iter).second;
}
唯一的堆分配部分可能是值*(不太支持大写)。 对于析构函数,必须循环遍历映射并删除所有相关指针,如下所示
for(auto iter = IDX_TO_VAL.begin(); iter != IDX_TO_VAL.end(); ++iter)
{
delete (*iter).second;
}
为了避免在析构函数中手动释放所有
VALUE*
拥有的内存,您可能应该使用智能指针
C++11提供了std::shared_ptr
,可用于存储值*
typedef std::map<IDX, std::shared_ptr<VALUE> > IDX_TO_VAL;
typedef std::将IDX_映射到_VAL;
如果您可以使用boost库,那么您可以使用
boost::shared_ptr
来避免在析构函数中写入所有VALUE*
所拥有的手动释放内存-可能您应该使用智能指针
C++11提供了std::shared_ptr
,可用于存储值*
typedef std::map<IDX, std::shared_ptr<VALUE> > IDX_TO_VAL;
typedef std::将IDX_映射到_VAL;
如果您可以使用boost库,那么您可以使用
boost::shared_ptr
@unshul如果值指向堆上分配的某个对象怎么办?--如果它不指向该对象怎么办?如果您尝试对该值调用delete
,则会出现未定义的行为。这是您设计中的缺陷--您无法假设该地址来自该值您正在用@unshul填充映射。@如果值指向堆上分配的某个对象,该怎么办?--如果它不指向,该怎么办?如果您试图对该值调用delete
,则会出现未定义的行为。这是您设计中的缺陷--您无法假设填充映射时的地址来自何处。绝对:void insert(const std::string&key,std::unique_ptr value)
,答对了。如果您不喜欢在代码中表达需求,还可以传递一个原始指针,并在函数声明上方添加一条注释,说明//获得*value的所有权并在指针上调用“delete”。
。(很重要的一点是,用户不能传入从malloc
或从array-new
获取的指针,因此仅仅“获取所有权”是不够精确的。但唯一的指针不会留下任何歧义。)更好(平均而言)对于m_idx_to_name_map
和m_idx_to_val_map
,使用vector
s而不是map
s,因为索引是连续的(假设不支持删除)也有疑问,为什么你会有这样一个看似无关紧要的间接性和你的类的混合责任。为什么不拥有一个<代码>地图< /代码>?如果用户关心间接的,她可以使用<代码>值= STD::unQuueEYPTR 。你也可以考虑这样的双向映射。Kerrek提出的独立的建议。ibilities是目前为止最好的选择,而且unique\u ptr
只需一秒钟,但FWIW的另一个选择是使用模板策略参数或构造函数参数指定可以调用以取消分配的函子(如有必要)值*
。另外,最好的做法是为预处理器宏保留所有大写标识符,但可用于模板参数的单字母标识符除外。绝对:void insert(const std::string&key,std::unique\u ptr VALUE)
,答对了。如果您不喜欢在代码中表达需求,还可以传递一个原始指针,并在函数声明上方添加一条注释,说明//获取*值的所有权并在指针上调用“delete”。
。(很重要的一点是,用户不能传入从malloc
或从array-new
获取的指针,因此仅仅“获取所有权”是不够精确的。但唯一的指针不会留下任何歧义。)更好(平均而言)对于m_idx_to_name_map
和m_idx_to_val_map
,使用vector
s而不是map
s,因为索引是连续的(假设不支持删除)也有疑问,为什么你会有这样一个看似无关紧要的间接性和你的类的混合责任。为什么不拥有一个<代码>地图< /代码>?如果用户关心间接的,她可以使用<代码>值= STD::unQuueEYPTR 。你也可以考虑这样的双向映射。Kerrek提出的独立的建议。ibilities是目前为止最好的选择,而且unique\u ptr
只需一秒钟,但FWIW的另一个选择是让模板策略参数或构造函数参数指定一个可以调用的函子来取消分配(如有必要)值*
.Sep