我已经定义了一个名为ClusterSet的类,它只有一个字段,名为clusters
:
class ClusterSet {
std::map<std::string, std::map<std::string, float>* > clusters;
public:
typedef std::map<std::string, std::map<std::string, float> *>::iterator iterator;
typedef std::map<std::string, std::map<std::string, float> *>::const_iterator const_iterator;
iterator begin() { return clusters.begin(); }
const_iterator begin() const { return clusters.begin(); }
iterator end() { return clusters.end(); }
const_iterator end() const { return clusters.end(); }
void create_cluster(std::string representative);
void add_member(std::string representative, std::string member, float similarity);
int write_to_file(std::string outputfile);
int size();
~ClusterSet();
};
在我的create_cluster
方法中,我使用new
为内部地图分配内存,并将此指针存储在clusters
中。我定义了一个析构函数,以便我可以释放所有这些内存:
ClusterSet::~ClusterSet() {
ClusterSet::iterator clust_it;
for (clust_it = clusters.begin(); clust_it != clusters.end(); ++clust_it) {
std::cout << "Deleting members for " << clust_it->first << std::endl;
delete clust_it->second;
}
}
当我的析构函数被调用时,它似乎正确地释放了所有内部映射(它为每个映射打印出“删除成员......”)。然而,一旦完成,我得到一个运行时错误,说“未能”munmap“1068字节:无效的参数”。造成这种情况的原因是什么?
我简要地看过“三个规则”,但我不明白为什么我需要一个复制构造函数或赋值运算符,或者如何解决我的问题。我永远不需要直接使用。
答案 0 :(得分:1)
动态分配内部地图没有充分的理由(以及很多缺点)。将外部地图类型更改为
std::map<std::string, std::map<std::string, float> >
然后你根本不需要实现自己的析构函数和复制/移动语义(除非你想改变你从地图中获得的那些,可能是为了防止复制你的类)。
如果在其他情况下,您确实需要存储指向对象的指针和将其生命周期与地图中的存在联系起来,请存储智能指针:
std::map<std::string, std::unique_ptr<something> >
如果你真的想要出于某种原因手工管理它们的生命周期,那么你将需要遵循规则三并给你的类有效的复制语义(通过删除复制构造函数/赋值运算符来防止复制,或者实现任何你想要的语义)。即使你不认为你正在复制对象,编写代码也很容易。