I was unsure about whether STL containers are entirely copied when passed. First, it worked (so the "fluttershy" element didn't get added, that was good). Then I wanted to track the construction and destruction of entries....
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
using namespace std;
int nextid = 0;
class Entry {
public:
string data;
int myid;
Entry(string in) {
data = in;
myid = nextid;
nextid++;
printf("Entry%02d\n", myid);
}
~Entry() { printf("~Entry%02d\n", myid); }
};
class Meep {
public:
vector<Entry> stuff;
};
void think(Meep m) {
m.stuff.push_back(Entry(string("fluttershy")));
}
int main() {
Meep a;
a.stuff.push_back(Entry(string("applejack")));
think(a);
vector<Entry>::iterator it;
int i = 0;
for (it=a.stuff.begin(); it!=a.stuff.end(); it++) {
printf("a.stuff[%d] = %s\n", i, (*it).data.c_str());
i++;
}
return 0;
}
Produces the following unexpected output( http://ideone.com/FK2Pbp ):
Entry00
~Entry00
Entry01
~Entry00
~Entry01
~Entry00
~Entry01
a.stuff[0] = applejack
~Entry00
That a has only one element is expected, that is not the question. What seriously confuses me is how can one entry be destructed several times ?
What you're seeing is the destruction of temporary instances.
a.stuff.push_back(Entry(string("applejack")));
This line creates a temporary instance which is then copied to another new instance in the container. Then the temporary is destroyed. The instance in the container is destroyed when the entry is removed or the container is destroyed.
Related
I have a class that has a constructor. I now need to make a map with it as a value how do I do this? Right now without a constructor I do.
#include <iostream>
#include <map>
using namespace std;
class testclass {
public:
int x = 1;
};
int main()
{
map<int,testclass> thismap;
testclass &x = thismap[2];
}
If I added a constructor with arguments how would I add them to the map? I basically need to do
#include <iostream>
#include <map>
using namespace std;
class testclass {
public:
int x = 1;
testclass(int arg) {
x = arg;
}
};
int main()
{
map<int,testclass> thismap;
testclass &x = thismap[2];
}
This obviously wouldn't work since it requires an argument but I can't figure a way of doing this.
This is how you can add items of your own class to your map.
Note : I used a string in testclass to better show difference
between key and value/class.
#include <iostream>
#include <string>
#include <map>
class testclass
{
public:
explicit testclass(const std::string& name) :
m_name{ name }
{
};
const std::string& name() const
{
return m_name;
}
private:
std::string m_name;
};
int main()
{
std::map<int, testclass> mymap;
// emplace will call constructor of testclass with "one", and "two"
// and efficiently place the newly constructed object in the map
mymap.emplace(1, "one");
mymap.emplace(2, "two");
std::cout << mymap.at(1).name() << std::endl;
std::cout << mymap.at(2).name() << std::endl;
}
Using std::map::operator[] requires that the mapped type is default-constructible, since it must be able to construct an element if one doesn't already exist.
If your mapped type is not default-constructible, you can add elements with std::map::emplace, but you still can't use std::map::operator[] to search, you will need to use std::map::find() or so.
That's a rather obvious feature of std::map (and very similar other std containers). Some of their operations require specific type requirements for good reasons.
There is no problem to create such a map as you suggest in the first place, however, you are restricted to method calls that do not require potential default construction. The operator[] is such a method, since in the case the element is not found, it is created. That is what does not work in your example. Just use other methods with little impact on the map usage and you can still succeed:
#include <iostream>
#include <map>
using namespace std;
class testclass {
public:
int x = 1;
testclass(int arg) {
x = arg;
}
};
int main()
{
map<int,testclass> thismap;
thismap.insert( {2, testclass(5)} );
auto element2 = thismap.find(2);
if (element2 != thismap.end()) {
testclass& thiselement = element2->second;
cout << "element 2 found in map, value=" << thiselement.x << endl;
}
auto element5 = thismap.find(5);
if (element5 == thismap.end()) {
cout << "no element with key 5 in thismap. Error handling." << endl;
}
}
Main issue: avoid operator[].
Note:
Looking at the other very good answers, there are a lot of methods that can be used without default construction. There is not "right" or "wrong" since this simply depends on your application. at and emplace are prime examples that are highly advisable.
I have written a customized hash map, whose value contains an std::vector. And it caused core dump in real environment. There is a simplified example below. There are three questions:
Why vector size doesn't change to zero when I called the destruct function ~Value()? Does this program really release the memory allocated by vector before when I call the destruct function? And when I gdb attaches to this program, it's __M_start and __M_finish pointer still point to the same address.
Add1 and Add2 both have memory problems. Add1 won't call the construct function of vector, when I push_back int* to the vector of Value which has been erase before, it might be added to an illegal address. When I want to use the Add2 function to call the copy construct function, it might cause segment fault. Why it is still not working with Add2?
How should I change my program if I still want to use my customized map instead of std::map?
#include <iostream>
#include <functional>
#include <cstdlib>
#include <stdio.h>
#include <memory>
#include <vector>
#include <algorithm>
#include<iterator>
#include <map>
#include <iterator>
#include <limits>
#include <set>
using namespace std;
class Value
{
public:
// Value()
// {
// }
// Value(const Value &obj): stArr(obj.stArr)
// {
// cout<<"Call copy construct"<<endl;
// }
vector<int*> stArr;
};
class CustomMap
{
public:
// normal way
void Add1(int key, const Value& val)
{
stArrVal[key] = val;
}
// placement new
void Add2(int key, const Value& val)
{
new (&stArrVal[key]) Value(val);
// stArrVal[key] = val;
}
// void Add2(int key, const Value& val)
// {
// new (&stArrVal[key]) Value(val);
// }
void Erase(int key)
{
stArrVal[key].~Value();
// stArrVal[key].stArr.clear();
cout<<stArrVal[key].stArr.size()<<endl;
}
void Search(int key, Value *&pstVal)
{
pstVal = &stArrVal[key];
}
Value stArrVal[100];
};
void PrintValAddress(Value *pVal)
{
for (const auto & val : pVal->stArr)
{
cout<<&val<<", ";
}
cout<<endl;
}
int main()
{
vector<int> arr;
arr.push_back(1);
arr.push_back(3);
std::map<int, Value> stlMap;
CustomMap customMap;
Value* value = new Value();
Value* value2 = new Value();
int a = 1;
int b = 2;
int c = 3;
value->stArr.push_back(&a);
value->stArr.push_back(&b);
value->stArr.push_back(&c);
value2->stArr.push_back(&a);
value2->stArr.push_back(&b);
value2->stArr.push_back(&c);
// value2->stArr.push_back(&d);
stlMap.insert(pair<int, Value>(1, *value));
Value &stlV = stlMap[1];
Value *pstCusV = NULL;
customMap.Add1(1, *value);
customMap.Add2(2, *value);
customMap.Search(1, pstCusV);
PrintValAddress(pstCusV);
customMap.Search(2, pstCusV);
PrintValAddress(pstCusV);
// Release
customMap.Erase(1);
customMap.Erase(2);
// this line will cause segment fault.
// int* arr2 = new int[1024*1024];
customMap.Search(2, pstCusV);
// 1. still size 3
PrintValAddress(pstCusV);
// int* arr1 = new int[10];
customMap.Add1(1, *value2);
customMap.Add2(2, *value2);
customMap.Search(1, pstCusV);
PrintValAddress(pstCusV);
customMap.Search(2, pstCusV);
PrintValAddress(pstCusV);
return 0;
}
Output:
0xa14090, 0xa14098, 0xa140a0,
0xa14160, 0xa14168, 0xa14170,
3
3
0xa14160, 0xa14168, 0xa14170,
0xa14090, 0xa14098, 0xa140a0,
0xa14160, 0xa14168, 0xa14170,
Thanks a lot!
I need to copy the contents of a std::list into an array, wherein the array is struct of array. Below is the code implementation of it.
#include <iostream>
#include <string>
using namespace std;
typedef struct
{
int height;
int width;
int length;
}dimensions;
GetDimensions(list<std::string>, *int); // Function that copies the content of list to array passed as second parameter
int main()
{
dimensions cuboid[10];
int plane[10];
list<std::string> planeList = GetList();//Function that returns list of elements
list<std::string> dimensionList = GetList();
GetDimensions(planeList,&plane);//This is fine, as it is a simple array
GetDimensions(dimensionList,&cuboid.height);//Trouble in implementation of this usecase, for cuboid.height, cuboid.width and cuboid.height.
return 0;
}
GetDimensions(list<std::string>dimensionList, int* dimensionParams)
{
int i=0;
for(list<std::string>::iterator it = dimensionList.begin(); it != dimensionList.end(); ++it)
{
dimensionParams[i] = stoi(*it);
i++;
}
}
Here, I need GetDimensions() function to copy the list (passed as first parameter) to array (second parameter). The implemented function works well for simple array plane. But how to pass the array of struct as parameter to the function ?
I will be getting the std::list as cuboid.height, cuboid.width and cuboid.length. So the function has to copy the contents of list from cuboid[0].height to cuboid[i].height respectively. Is there any specific function to copy the content directly?
Use std::array 's instead. Then your problem can be reduced to passing two different types of arrays to a single function.
This can be solved
either by good old function overloads
or in c++17 function template with
if-constexpr.
Following is an example code with templated function with if-constexpr (See live online)
#include <iostream>
#include <string>
#include <list>
#include <array>
#include <type_traits> // std::is_same_v
struct dimensions // no need to typedef here
{
int height;
int width;
int length;
};
template<typename T>
void GetDimensions(const list<std::string>& dimensionList, T& dimensionParams)
^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //---> pass list by const-ref as the values are non-modifying
{
int i{0};
if constexpr (std::is_same_v<std::array<int, 10>, T>)
{
for(const std::string& str: dimensionList) dimensionParams[i++] = std::stoi(str);
}
else
{
for(const std::string& str: dimensionList) dimensionParams[i++].height = std::stoi(str);
}
}
int main()
{
std::array<dimensions, 10> cuboid; // use std::array instead of VLA
std::array<int, 10> plane;
std::list<std::string> planeList{"1", "2"}; // some list
std::list<std::string> dimensionList{"1", "2"};
GetDimensions(planeList, plane);
GetDimensions(dimensionList, cuboid);
return 0;
}
Also note that:
You have not specified the return type of GetDimensions function.
You probably want to return void there.
in C++ you do not need to use typedef alias for struct { ... }.
last but not least, do not practice with using namespace std;
You can do this with boost::transform_iterator.
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
#include <boost/iterator/transform_iterator.hpp>
struct dimensions {
int height;
int width;
int length;
};
template <typename OutputIt>
void GetDimensions(std::list<std::string> dimensionList, OutputIt dimensionParams)
{
// N.b. taking the address of a standard library function is undefined, so wrap in a lambda
auto stoi = [](std::string s){ return std::stoi(s); };
std::copy(boost::make_transform_iterator(dimensionList.begin(), stoi),
boost::make_transform_iterator(dimensionList.end(), stoi),
dimensionParams);
}
int main() {
dimensions cuboid[10];
int plane[10];
std::list<std::string> planeList = GetList();
std::list<std::string> heightList = GetList();
std::list<std::string> widthList = GetList();
std::list<std::string> lengthList = GetList();
GetDimensions(planeList, plane);
GetDimensions(heightList,
boost::make_transform_iterator(cuboid, std::mem_fn(&dimensions::height)));
GetDimensions(widthList,
boost::make_transform_iterator(cuboid, std::mem_fn(&dimensions::width)));
GetDimensions(lengthList,
boost::make_transform_iterator(cuboid, std::mem_fn(&dimensions::length)));
return 0;
}
A member of a class is a reference to a local variable. When the local variable is destructed, and the object of this class still exists, you can access the destructed local variable through this object. Why?
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
class c2
{
public:
int& a;
c2(int & c):a(c)
{
}
};
int main()
{
c2 * p;
{
int i = 20;
p = new c2(i);
}
cout << p->a;
system("pause");
return 0;
}
As pointed out by some comments above, the behavior is actually undefined. See in particular the c++ reference on the Lifetime of a temporary:
a temporary bound to a reference in the initializer used in a
new-expression exists until the end of the full expression containing
that new-expression, not as long as the initialized object. If the
initialized object outlives the full expression, its reference member
becomes a dangling reference.
If you use gcc or clang you can compile the program with the option -fsanitize=address: it will crash with
ERROR: AddressSanitizer: stack-use-after-scope
Instead, you will not get any error if you modify your program as follows:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
class c2
{
public:
int& a;
c2(int & c):a(c)
{
}
};
int main()
{
c2 * p;
{
int i = 20;
p = new c2(i);
cout << p->a;
}
delete p;
return 0;
}
(In the program I have inserted a delete p to avoid memory leak)
I have a class Branch and a class Tree. The declaration of the classes looks like:
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) If I understood well, the fact that the only attributes of Tree class are a vector and a map, makes it unnecessary to declare a destructor, a copy-assignement operator and a copy constructor, because the memory is managed "inside" the vector and map templates.
2) I use this classes from a python code (I used cython to interface between C++ an python) and all the operations I make are performed through a tree object. I thought that because the branches I "use" are contained in a tree object (with a good memory management) I didn't need to declare a destructor, a copy constructor,and a copy assignment operator for the branch class. However I'm experiencing some problems and I think I have a memory leak.
Can someone confirm me if this could be causing a memory leak? If it is would stocking the int hierarchy inside a vector<int> avoid declaring a destructor and company?
EDIT
The branches who are stocked in the tree are created inside a method of the Tree class. It looks like:
Tree::addBranch(){
Branch* branch2insert=new Branch();
tree_branches.push_back(branch2insert);
}
As a local variable, is branch2insert destructed at the end of the scope? Do I need to write delete branch2insert;? Does someone have an idea of where do the Branch object at which I point to lives?
I still don't get why I need to ensure memory management when I never allocate ressources except inside the Tree class methods...
This whole thing is getting very messy in my head
EDIT 2:EXAMPLE
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;
}
to compile:
g++ -Wall -pedantic -c
1) If I understood well, the fact that the only attributes of Tree class are a vector and a map, makes it unnecessary to declare a destructor, a copy-assignement operator and a copy constructor, because the memory is managed "inside" the vector and map templates.
You are wrong here, as the memory which is managed inside the vector is only the storage for the addresses of branches(Branch *). When you insert some branch you call something like tree_branches.push_back(new Branch), don't you? Thus, you will need to call the corresponding delete somehow, otherwise the default destructor of the tree won't take care of calling the destructors of the Branches.
A quick fix for your code could be switching from Branch * to shared_ptr<Branch>. In such way, when the tree_branches vector is destroyed, the shared_ptr's will also be destroyed and when the latest shared_ptr to any Branchis destroyed, also the pointed Branch will be.
would stocking the int hierarchy inside a vector avoid declaring a destructor and company?
It would change jack squat, as the Branches default destructors still would not be called, and so the destructors of the Branches members would never be called.
Finnally there isn't a memory leak. Thanks #Yunnosch for mentionning Valgrind, I wasn't aware this kind of tool existed.
#Davide I accepted your answer since it provided an alternative to what I've done, even if apparently there aren't problems with the management of the memory in my code.
The code I posted has a problem in function Tree::getLastDescendantIndex.