我有一个班级Branch
和一个班级Tree
。类的声明如下:
class Branch{
private:
map<string, double> properties;
vector<Branch *> parent;
vector<Branch *> children;
int hierarchy;
public:
...
}
class Tree{
private:
/* Tree is a vector of pointers to branches. */
vector<Branch*> tree_branches;
map<int,int> Hierarchy_distribution;
public:
...
}
1)如果我理解得很清楚,Tree
类的唯一属性是vector
和map
,则无需声明析构函数,副本分配运算符和复制构造函数,因为内存管理&#34;内部&#34;矢量和地图模板。
2)我使用python代码中的这些类(我使用cython在C ++和python之间进行接口),我所做的所有操作都是通过树对象执行的。我认为这是因为分支机构I&#34;使用&#34;包含在树对象中(具有良好的内存管理)我不需要为分支类声明析构函数,复制构造函数和复制赋值运算符。但是,我遇到了一些问题,我认为我有内存泄漏。
有人可以确认我是否会导致内存泄漏吗?如果它会将int hierarchy
放在vector<int>
内,避免声明析构函数和公司?
修改
树中存储的分支是在Tree
类的方法内创建的。它看起来像:
Tree::addBranch(){
Branch* branch2insert=new Branch();
tree_branches.push_back(branch2insert);
}
作为局部变量,在范围的末尾被branch2insert
破坏?我需要写delete branch2insert;
吗?有人知道我指向的Branch
对象在哪里生活吗?
我仍然不知道为什么我需要确保内存管理,除非在Tree
类方法中,我从不分配资源......
这整件事情在我脑海里变得非常凌乱
编辑2:示例
branch.h
#ifndef BRANCH_H_
#define BRANCH_H_
#include <memory>
#include <string>
#include <vector>
#include <map>
using namespace std;
class Branch{
private:
vector<Branch*> parent;
vector<Branch*> children;
public:
Branch();
bool hasParent();
bool hasParent(Branch* test);
void addParent(Branch* p);
void removeParent();
Branch* getParent();
bool hasChildren();
bool hasChild(Branch*test);
void addChild(Branch*ch);
void removeChild(Branch*ch);
void removeChildren();
void removeDescendants();
vector<Branch*> getBrothers();
};
#endif
tree.h中
#ifndef TREE_H_
#define TREE_H_
#include <vector>
#include <map>
#include"branch.h"
using namespace std;
class Tree{
private:
vector<Branch*> tree_branches;
public:
Tree();
int getNumberOfBranches();
Branch* getBranch(int branch_index); /* Returns branch at index. */
int getIndex(Branch* branch); /* Returns the index of branch. */
int getLastDescendantIndex(int ancestor_index); /* Returns index of the last descendant of branch at ancestor index. */
int getParentIndex(int child_index); /* Returns index of the parent of branch at child_index. */
vector<int> getBrothersIndex(int branch_index); /* Returns indexes of the brothers of branch at branch_index. */
void addBranch(int parent_index); /* Adds branch without initializing its properties. */
void removeBranch(int branch_index); /* Removes branch at branch_index and all its descendants. */
};
#endif
branch.cpp
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <sstream>
#include <map>
#include <stdio.h>
using namespace std;
#include "branch.h"
Branch::Branch():parent(vector<Branch*>()),children(vector<Branch*>())
{
}
bool Branch::hasParent(){
if(parent.size()==0)
return false;
else
return true;
}
bool Branch::hasParent(Branch* test){
bool ret = false;
for(vector<Branch*>::iterator it=parent.begin();it!=parent.end();it++){//traversing parent vector
if((*it)==test){//if test belong to parent vector
ret = true;
break;
}
}
return ret;
}
void Branch::addParent(Branch* mom){
if(parent.size()==0){//if a branch hasn't a parent, multiple parents aren't allowed in a tree-network
if(hasParent(mom)==false){//double checking if mom isn't already a parent
parent.push_back(mom);//adding mom to parent vector
}
else{
cout << "Branch::addParent Error: trying to add a parent twice.\n";
}
}
else{
cout << "Branch::addParent Error: trying to add a parent to a branch that already has one.\n";
}
}
void Branch::removeParent(){
if(this->hasParent()==true){//if this branch has a parent
vector<Branch*>::iterator it=parent.begin();
parent.erase(it);//erase it (it is the first and only element of the vector)
}
else{
cout << "Removing the trunk.\n";
}
}
Branch* Branch::getParent(){
return parent[0];
}
bool Branch::hasChildren(){
if(children.size()==0)
return false;
else
return true;
}
bool Branch::hasChild(Branch* test){
bool ret = false;
for(vector<Branch*>::iterator it=children.begin();it!=children.end();it++){
if((*it)==test){
ret = true;
break;
}
}
return ret;
}
void Branch::addChild(Branch* ch){
if(hasChild(ch)==false){
children.push_back(ch);
ch->addParent(this); // PARENTHOOD LINK ESTABLISHED IN ADD CHILD. ONLY
// NEEDED ONCE.
}
else{
cout << "Branch::addChild Error: trying to add a child but the child has been already added.\n";
}
}
void Branch::removeChild(Branch* ch){
if(hasChild(ch)==true){
for(vector<Branch*>::iterator it=children.begin();it!=children.end();it++){
if((*it)==ch){
children.erase(it);
break;
}
}
}
else{
cout << "Branch::removeChild Error: trying to remove a child that doesn't exist.\n";
}
}
void Branch::removeChildren(){
if(this->hasChildren()==true){
children.erase(children.begin(),children.end());
}
else{
cout << "Branch::removeChildren Error: trying to remove all the children of a branch but tha branch hasn't any.\n";
}
}
void Branch::removeDescendants(){
if (this!=NULL){
if(this->hasChildren()==true){
for(vector<Branch*>::iterator it=children.begin();it!=children.end();it++){
(*it)->removeDescendants();
}
removeChildren();
}
for(vector<Branch*>::iterator it=children.begin();it!=children.end();it++){
(*it)->removeParent();
}
}
}
vector<Branch*> Branch::getBrothers(){
vector<Branch*> brothers;
vector<Branch*> potential_brothers;
if (parent.size()!=0){
potential_brothers=parent[0]->children;
for (vector<Branch*>::iterator it=potential_brothers.begin();it!=potential_brothers.end();it++){
if ((*it)!=this){
brothers.push_back((*it));
}
}
}
return brothers;
}
tree.cpp
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
#include "tree.h"
Tree::Tree():tree_branches(vector<Branch*>()){
Branch* trunk=new Branch();
tree_branches.push_back(trunk);
}
int Tree::getNumberOfBranches(){
int number_of_branches=tree_branches.size(); //retrieving size of vector
return number_of_branches;
}
Branch* Tree::getBranch(int index){
unsigned int u_index=index;
return tree_branches.at(u_index); // returning branch at index of the tree vector
}
int Tree::getIndex(Branch* branch){
int index=0;
for(vector<Branch*>::iterator it=tree_branches.begin();it!=tree_branches.end();it++){
if((*it)==branch){
return index;
}
index++;
}
cout << "Tree::getIndex Error: trying to get the index of a branch we can't find. Returning 0.\n";
return 0;
}
int Tree::getLastDescendantIndex(int ancestor_index){
if(tree_branches.at(ancestor_index)->hasChildren()==false){// if it is a leaf
return ancestor_index;
}
if(ancestor_index==0){// if it is the trunk
int N=tree_branches.size();
int last_descendant_index=N-1;
return last_descendant_index;
}
vector<int> brothers_indexes=Tree::getBrothersIndex(ancestor_index);
for(vector<int>::iterator it=brothers_indexes.begin();it!=brothers_indexes.end();it++){
int brother_index=(*it);
if(brother_index>ancestor_index){
int last_descendant_index=brother_index-1;
cout << "The last descendant of" << ancestor_index << " is "<<last_descendant_index<<"\n";
return last_descendant_index;
}
}
int parent_index=Tree::getParentIndex(ancestor_index);
Tree::getLastDescendantIndex(parent_index);
}
int Tree::getParentIndex(int child_index){
if(child_index==0){ //if considered branch is the trunk
cout << "Tree::getParentIndex: the trunk hasn't a parent. Returning -1.\n";
return -1;
}
unsigned int u_child_index=child_index;
Branch* parent=tree_branches.at(u_child_index)->getParent(); //retrieving the parent of the considered branch
int parent_index=Tree::getIndex(parent);
return parent_index; //returning parent index
}
vector<int> Tree::getBrothersIndex(int branch_index){
vector<int> brothers_index;
Branch* this_branch=Tree::getBranch(branch_index);//retrieving the branch from the index
vector<Branch*> brothers=this_branch->getBrothers();//retrieving branch's brothers
for(vector<Branch*>::iterator it=brothers.begin();it!=brothers.end();it++){ //traversing a vector containing the brothers of the consideered branch
int this_index=Tree::getIndex(*it); //retrieving index of a brother
brothers_index.push_back(this_index); //stocking the index in a vector
}
return brothers_index; //returning the vector containing the index of all brothers
}
void Tree::addBranch(int parent_index){
unsigned int u_parent_index=parent_index;
Branch* mom=tree_branches.at(u_parent_index);//getting futur parent
Branch* branch2insert=new Branch();//creation of branch to insert
mom->addChild(branch2insert);//setting family relationship
vector<Branch*>::iterator begin=tree_branches.begin();//creating iterators to manipulate vector elements
unsigned int inserting_position=u_parent_index+1;//initializing inserting_position
tree_branches.insert(begin+inserting_position,branch2insert);//inserting new branch
}
void Tree::removeBranch(int branch_index){
int N=tree_branches.size();
unsigned int u_branch_index=branch_index;
Branch* branch2remove=tree_branches.at(u_branch_index);
branch2remove->removeParent(); //removing parenthood link, if branch2remove is the trunk nothing will be done
if(branch_index!=0){//removing childhood link between parent and branch_index
Branch* branch2removeParent=branch2remove->getParent();
branch2removeParent->removeChild(branch2remove);
}
int last_descendant_index=Tree::getLastDescendantIndex(branch_index);
cout<<"The branch to remove is "<<branch_index<<", its last descendant index is "<<last_descendant_index<<", the size of the tree is "<<N<<".\n";
branch2remove->removeDescendants();//removing family links for all descendents
if(last_descendant_index==N-1){
vector<Branch*>::iterator begin=tree_branches.begin();
tree_branches.erase(tree_branches.begin()+u_branch_index,tree_branches.end());
}
else{
vector<Branch*>::iterator begin=tree_branches.begin();
unsigned int u_last_descendant_index=last_descendant_index;
tree_branches.erase(tree_branches.begin()+u_branch_index,tree_branches.begin()+u_last_descendant_index+1);//removing the considered branch and its descendents from the tree vector
}
}
TEST.CPP
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <typeinfo>
#include <vector>
#include <map>
#include <string>
#include "tree.h"
using namespace std;
int main(){
Tree tree;
tree=Tree();
for(int i=0;i<5;i++){
int N=tree.getNumberOfBranches();
for(int j=0;j<N;j++){
tree.addBranch(j);
tree.addBranch(j);
}
}
tree.removeBranch(21);
tree.removeBranch(30);
tree.removeBranch(50);
return 0;
}
编译:
g ++ -Wall -pedantic -c
答案 0 :(得分:3)
1)如果我理解得很好,Tree类的唯一属性是向量和映射,则不需要声明析构函数,复制 - 分配运算符和复制构造函数,因为内存是受管理的#34;内部&#34;矢量和地图模板。
这里你错了,因为在向量内部管理的内存只是分支地址的存储(Branch *
)。当您插入某个分支时,您会调用类似tree_branches.push_back(new Branch)
的内容,不要?因此,您需要以某种方式调用相应的delete
,否则树的默认析构函数不会负责调用Branch
es的析构函数。
对代码的快速修复可能会从Branch *
切换到shared_ptr<Branch>
。这样,当tree_branches
向量被销毁时,shared_ptr
也将被销毁,当最新的shared_ptr
到任何Branch
被销毁时,指向的Branch
将是。
将int层次结构存储在向量中,避免声明析构函数和公司吗?
它会改变插孔深蹲,因为Branch
默认析构函数仍然不会被调用,因此永远不会调用Branch
es成员的析构函数。
答案 1 :(得分:0)
最终没有内存泄漏。感谢@Yunnosch提到Valgrind,我不知道这种工具存在。
@Davide我接受了你的答案,因为它为我所做的提供了一个替代方案,即使我的代码中的内存管理显然没有问题。
我发布的代码在函数Tree :: getLastDescendantIndex中存在问题。