std::list looping forever, scope issue? - c++

I have a Node class. It contains x,y coordinates, an id and a list of Node pointers which holds the adjacent nodes.
I am having problem with the list data structure inside the class. The printAdj() function works fine but I need to iterate through the adjacency list of a node from outside the class by acquiring adjList member using adjs() function.
class Node{
public:
// constructors & destructors
Node(double x, double y, unsigned id) : x_(x), y_(y),
id_(id) {}
// setters & getters
std::list<Node*> adjs() const { return adjList; }
// member functions
void addAdj(Node* n) { adjList.push_back(n); }
void printAdj() const{
for(std::list<Node*>::const_iterator it = adjList.begin();
it != adjList.end() ; ++it){
std::cout << "\t" << (*it)->id() << " " << std::endl;
}
}
private:
std::list<Node*> adjList;
double x_, y_;
unsigned id_;
};
The outside loop runs forever.
list<Node*> RRT_graph; //global
void print(){
for(list<Node*>::const_iterator it = RRT_graph.begin() ;
it != RRT_graph.end() ; ++it){
cout << "Node ID: " << (*it)->id() << "\tX: " << (*it)->x()
<< "\tY: " << (*it)->y() << endl;
cout << "\tAdjacency List:" << endl;
(*it)->printAdj(); // member function correctly prints adjacency list
// nothing wrong with the size, it displays correctly
cout << "-----------------------------------" << endl;
cout << "(" << (*it)->adjs().size() << ")" << endl;
// but when the list is looped, it goes forever.
unsigned count = 0;
for(list<Node*>::const_iterator ite = (*it)->adjs().begin() ;
ite != (*it)->adjs().end() ; ++ite)
cout << count++ << endl;
}
Since two adjacency list printing loops are identical and only member function works, I suspect a scope issue here but I'm sort of lost.
What's wrong here?

Just return const reference in adjs(), it should work. Currently it is returning a copy, hence when you take iterator in (*it)->adjs().begin() and in (*it)->adjs().end(), it gives iterators to different copies
const std::list<Node*>& adjs() const { return adjList; }

Related

C++ Dynamically allocate a structure which contains an union[vec or map] twice leads to a bad_alloc error

I have a bunch of tuples (int array[N], string message) to store. I want to be able to add/delete a lot of elements from this array very quickly but, most importantly, given another array array2, I want to find every string such that for all i : array[i] <= array2[i] (not implemented yet).
Thus, I thought about using a tree of height N where a leaf is a message. If it is a leaf, it should contain a vector if it's a node, it should contain a map.
I am using an union to manage whether a tree is a leaf or a node.
My delete function should delete the leaf and all the nodes that lead only to this leaf.
I can insert a message (or multiple different messages). However, I can't reinsert a message that I previously deleted. It raises a bad_alloc error.
#include <iostream>
#include <map>
#include <vector>
using namespace std;
struct Node{
enum{LEAF, NODE} tag;
union {
std::map<int, struct Node*> map;
std::vector<std::string> msg;
};
Node(std::string m){
tag = LEAF;
cout << "Flag 1 : Crashing here, for some reasons a map is allocated" << "\n";
msg.push_back(m);
cout << "Flag 2 : Did you manage to fix it ?" << "\n";
}
Node(){
tag = NODE;
map = std::map<int, struct Node*>();
}
~Node(){
if (tag==NODE){
map.~map();
} else {
msg.~vector();
}
}
};
void insert(int* array, int size, Node* node, std::string msg){
cout << "Insert\n";
if (size > 1){
if (!node -> map.count(array[0])){
node->map[array[0]] = new Node();
}
insert(array+1, size-1, node->map[array[0]], msg);
} else {
if (!node->map.count(array[0])){
cout << "Case 1\n";
node -> map[array[0]] = new Node(msg);
}
else{
cout << "Case 2\n";
node -> map[array[0]]->msg.push_back(msg);
}
}
}
bool find(int * array, int size, Node * node){
if (!node -> map.count(array[0])){
return false;
}
if (size==1){
return true;
}
return find(array+1, size-1, node->map[array[0]]);
}
std::vector<std::string> find_vec(int * array, int size, Node * node){
if (!node -> map.count(array[0])){
return std::vector<std::string>();
}
if (size==1){
if (!node -> map.count(array[0])){
return std::vector<std::string>();
}
return node -> map[array[0]]->msg;
}
return find_vec(array+1, size-1, node->map[array[0]]);
}
void print_array(std::vector<std::string> v){
for (auto & elem : v){
cout << elem << " ";
}
cout << "\n";
}
void erase(int * array, int size, Node * node){
std::vector<Node*> vec;
int i = 0;
Node *t = node;
while (i < size){
if (t -> map.count(array[i])){
vec.push_back(t);
t = t-> map[array[i]];
} else
break;
i++;
}
if (i == size){
// Deleting the leaf
cout << "Deleting Leaf\n";
delete t;
cout << "Deleting vec [" << size-1 << "] elem " << array[size-1] << "\n";
cout << "Deleted ? " << vec[size-1]->map.erase(array[size-1]) << "\n";
// Deleting the path if it has no other leaf
cout << "Delete Path\n";
for (i = size-1; i > 0; i--){
//cout << "debut loop " << i << "\n";
//vec[i-1]->map.erase(array[i-1]);
if (!vec[i] -> map.size()){
delete vec[i];
cout << "Deleting vec [" << i-1 << "] elem " << array[i-1] << "\n";
cout << "Deleted ? " << vec[i-1]->map.erase(array[i-1]) << "\n";
}
else
break;
//cout << "fin loop\n";
}
}
}
int main()
{
Node * Tree = new Node;
for (int k = 0; k < 2; k++){
cout << "k = " << k << "\n---------------------------------------------------------------------------------------------\n";
int size = 4;
int array[4] = {0,1,2,3};
std::string m1 = "Random message that I want to store as many times as I want";
insert(array, size, Tree, m1);
cout << "find : " << find(array, size, Tree) << "\n";
std::vector<std::string> vec1 = find_vec(array, size, Tree);
cout << "vec ";
print_array(vec1);
cout << "-------------------\n";
erase(array, size, Tree);
cout << "We should find the message \n";
print_array(vec1);
cout << "-------------------\n";
cout << "We should not find the message \n";
vec1 = find_vec(array, size, Tree);
print_array(vec1);
cout << "-------------------\n";
}
return 0;
}
A union should be treated with care, especially when used with non-trivial members like in your example. Specifically of interest is this passage from cppreference:
If a union contains a non-static data member with a non-trivial
special member function (copy/move constructor, copy/move assignment,
or destructor), that function is deleted by default in the union and
needs to be defined explicitly by the programmer.
If a union contains a non-static data member with a non-trivial
default constructor, the default constructor of the union is deleted
by default unless a variant member of the union has a default member
initializer .
The map member is not constructed and therefore you cannot just start using it.
I recommend using std::variant as a safe alternative to a raw union. Your example would look like the following without a need for your enum:
struct Node {
std::variant<std::map<int, Node*>, std::vector<std::string>> data;
Node(std::string m){
data.emplace<1>();
cout << "Flag 1 : Crashing here, for some reasons a map is allocated" << "\n";
std::get<1>(data).push_back(m);
cout << "Flag 2 : Did you manage to fix it ?" << "\n";
}
// ...
};

Wrong destructor called by vector erase

I have a vector with some objects.
I noticed that when I remove one element from vector with erase method, I get the destructor call to the wrong element (always to the last element).
Here a minimal example that produce a bad output.
// Example program
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Test {
public:
Test(string value) {
_value = value;
cout << "Constructor:" << _value << endl;
}
Test(const Test &t) {
_value = t._value;
cout << "Copied:" << _value << endl;
}
~Test() {
cout << "Destructor:" << _value << endl;
}
string print() {
return _value;
}
string _value;
};
int main()
{
vector<Test> vec;
vec.reserve(3);
cout << "Creation" << endl << endl;
vec.push_back(Test("1"));
vec.push_back(Test("2"));
vec.push_back(Test("3"));
cout << endl << "Deleting" << endl << endl;
vec.erase(vec.begin()); // Here is called the element with value "3"
vec.erase(vec.begin()); // Here is called the element with value "3"
cout << endl << "Log" << endl << endl;
// But the final log print "3"
for (unsigned i = 0; i < vec.size(); i++) {
cout << vec[i].print()<<endl;
}
return 0;
}
The output is:
Creation
Constructor:1
Copied:1
Destructor:1
Constructor:2
Copied:2
Destructor:2
Constructor:3
Copied:3
Destructor:3
Deleting
Destructor:3 <-- WRONG, NEED TO BE 1
Destructor:3 <-- WRONG, NEED TO BE 2
Log
3
Destructor:3
I would solve this problem without change the container vector.
vec.erase(vec.begin()); does not destruct the first element. It overwrites it by shifting all of the subsequent ones by one place, using either the move- or copy-assignment operator. What remains of the last element after it has been moved from is then destructed, which is what you're observing.

Design pattern to create smart references to elements in a vector

Because references in a vector point to locations of memory and not the abstract element, it can cause a few problems when altering the memory of the vector.
If a reference points to an element in a vector, and then that element is shuffled to another spot in the vector, the reference doesn't track the element, and will point to incorrect data after the shuffle.
If a element is invalidated, you can still access that elements contents without any safety checks, if you declared a references before invalidating the element.
If the vector resizes, all current references may be invalidated.
I wrote an example program that demonstrates all three problems.
#include <iostream>
#include <vector>
struct entity { //Simple struct of data.
bool alive;
float data;
};
class manager {
std::vector<entity> vec;
size_t count; // Amount of currently alive entities
public:
//Reserves initial_amount of entities, all set to dead, count set to 0.
manager(size_t initial_amount) : vec(initial_amount, { false, 0.0f }), count(0) {}
entity& create(float f) {
vec[count] = {true, f};
return vec[count++];
}
void refresh() { //Two iterators, one starts at the front of the vector, the other at
size_t front = 0; //count. The front iterator searches for dead entities and swaps them
size_t back = count; //with alive entities from the back iterator. For each swap we decrement
//count by 1, with the final result being all alive entities are between
while(true) { //0 and count.
for( ; true; ++front) {
if (front > back) return;
if (!vec[front].alive) break;
}
for( ; true; --back) {
if (vec[back].alive) break;
if (back <= front) return;
}
std::swap(vec[back], vec[front]);
--count;
++front;
--back;
}
}
void grow(size_t n) {
vec.resize(n);
}
void print() { //Prints all alive entities.
for (size_t index = 0; index < count; index++)
std::cout << vec[index].data << " ";
std::cout << std::endl;
}
};
int main() {
using namespace std;
manager c(10);
entity& d1 = c.create(5.5);
entity& d2 = c.create(10.5);
entity& d3 = c.create(7.5);
// Correct behavior
cout << d1.data << endl; // 5.5
cout << d2.data << endl; // 10.5
cout << d3.data << endl; // 7.5
cout << endl;
d2.alive = false; // "Kill" the entity
c.refresh(); // removes all dead entities. (this will swap d2's and d3's data in the vector,
// but wont change the locations they point to)
// Oh no! d2 and d3 still point to the same locations in the vector and now their data
// is incorrect after the swap, also d2 is dead maybe that should just be an error.
cout << d1.data << endl; // 5.5
cout << d2.data << endl; // 7.5
cout << d3.data << endl; // 10.5
cout << endl;
c.print(); // Correct behavior, prints only alive entities.
cout << endl;
d3.data = 6.5; // Trying to change the value of d3, which should still be alive.
c.print(); // Error, because d3 still points to the 3rd slot the intended value hasn't been changed.
cout << endl;
c.grow(10000);
cout << d1.data << endl; // After resize all these references are invalidated,
cout << d2.data << endl; // and using them is undefined behavior.
cout << d3.data << endl;
return 0;
}
Is there a design pattern to create a smart reference or proxy type that solves these problems? An object that will track its elements position in the vector, does specific behavior if the element is alive or dead, and stay valid after a resize?
I'm fine with the implementation of the smart/proxy reference to not be an actual reference, could be a pointer, integer index, or whatever. But this is specifically for elements in a vector, not a linked-list, map, etc.
With std::vector<std::shared_ptr<entity>>, you may have the security you want:
class manager {
std::vector<std::shared_ptr<entity>> vec;
public:
//Reserves initial_amount of entities
explicit manager(size_t initial_amount) { vec.reserve(initial_amount); }
std::weak_ptr<entity> create(float f) {
vec.push_back(std::make_unique<entity>(entity{true, f}));
return vec.back();
}
void refresh() {
vec.erase(std::remove_if(vec.begin(), vec.end(),
[](const auto& ent) {return !ent->alive;}),
vec.end());
}
void grow(size_t n) { vec.reserve(n); }
void print() { //Prints all alive entities.
for (const auto& ent : vec)
std::cout << ent->data << " ";
std::cout << std::endl;
}
};
And then the test:
int main() {
manager c(10);
auto d1 = c.create(5.5);
auto d2 = c.create(10.5);
auto d3 = c.create(7.5);
// Correct behavior
if (auto e = d1.lock()) std::cout << e->data << std::endl; else std::cout << "Die\n"; // 5.5
if (auto e = d2.lock()) std::cout << e->data << std::endl; else std::cout << "Die\n"; // 10.5
if (auto e = d3.lock()) std::cout << e->data << std::endl; else std::cout << "Die\n"; // 7.5
std::cout << std::endl;
if (auto e = d2.lock()) e->alive = false; // "Kill" the entity
c.refresh(); // removes all dead entities.
if (auto e = d1.lock()) std::cout << e->data << std::endl; else std::cout << "Die\n"; // 5.5
if (auto e = d2.lock()) std::cout << e->data << std::endl; else std::cout << "Die\n"; // Die
if (auto e = d3.lock()) std::cout << e->data << std::endl; else std::cout << "Die\n"; // 10.5
std::cout << std::endl;
c.print(); // Correct behavior, prints only alive entities.
std::cout << std::endl;
if (auto e = d3.lock()) e->data = 6.5; // Trying to change the value of d3,
// which should still be alive.
c.print();
std::cout << std::endl;
c.grow(10000);
if (auto e = d1.lock()) std::cout << e->data << std::endl; else std::cout << "Die\n"; // 5.5
if (auto e = d2.lock()) std::cout << e->data << std::endl; else std::cout << "Die\n"; // Die
if (auto e = d3.lock()) std::cout << e->data << std::endl; else std::cout << "Die\n"; // 6.5
}
Demo

how to know the element type of void* array in c++

first I'm working on compiler project , I've built a symbol table
class SymbolTable
{
Scope * currScope;
Scope * rootScope;
...
}
//where scope is
class Scope{
Scope();
Scope * parent;
MyMap * m;
...
};
//and Mymap is
class MyMap
{
static const int mapLength = MAX_LENGTH;
MapElem * arr[mapLength];
int hash(char* name);
...
}
//MapElem is
class MapElem{
char* name;
void* elem;
MapElem * next;
...
}
Now the Void* elem , can be ((function , class, variable ,scope)) all of them r classes,
I want to print the Symbol table to check what Yacc and parser are doing !!
I tried to do this :
void printScope(Scope *s)
{
if (s != NULL)
{
cout << "{";
for (int i = 0; i < 71; i++)
{
MapElem* tempelem = s->m->getbyId(i);
while (tempelem != NULL)
{
//cout << "element name is" << tempelem->getName();
if (static_cast <Type*> (tempelem->getElem())){
Type* t = (Type*)tempelem->getElem();
cout << "element is Class it's name is" << t->getIs_final() << " " << t->get_name() << "(";
for (int i = 0; i < t->getInheritedType().size(); i++){
if (t->getInheritedType()[i] != NULL)
cout << t->getInheritedType()[i]->get_name() << "," << endl;
}
cout << "):" << endl;
printScope(t->getScope());
}
else if (static_cast <Function*>(tempelem->getElem())){
Function* t = (Function*)tempelem->getElem();
cout << "element is Function it's name is" << t->get_final() << " " << t->get_name() << "(";
vector<Variable *> paramet = t->getparameters();
for (int i = 0;i< paramet.size(); i++){
cout << paramet[i]->get_name() << "," << endl;
}
cout << "):" << endl;
printScope(t->getScope());
}
else if ((Scope*)tempelem->getElem()){
Scope* t = (Scope*)tempelem->getElem();
printScope(t);
}
else if ((Variable*)tempelem->getElem()){
Variable* t = (Variable*)tempelem->getElem();
cout << "element is Variable it's name is" << t->getAccessModifier() << " " << t->get_name() << endl;
}
tempelem = tempelem->getNext();
}
}
cout << "}"<<endl;
}
}
the code is running perfect but it's doesn't check the [void type] in If statement ,always enter the first condition even the casting is wrong ,
in that order always enter the type even the void is function or variable ???
when I replaced them , also enter the first stmt what ever is it !!!
why that ?? and how I can fix it ?? or how I can know what data type must I cast .
The traditional answer is to add an enumeration to MapElem to indicate the type:
class MapElem{
//Enumeration identifying all the types of map element and indicating the contents of elem.
typedef enum {
aFunction,
aClass,
aVariable,
aScope
} Type;
char* name;
Type type; //<---- Tells us what elem really is!
void* elem;
MapElem * next;
...
};
The more OO way is to introduce a base class and sub-classes for each type.
You might find that a bit cumbersome because the variables types (function,class,variable and scope) are so divergent that your base-class will contain little more than a way of extracting type!
Oh and some method that returns a printable string for inspecting the elements...
You might introduce a virtual member that returns the enumeration type or rely on RTTI.
RTTI is usually a mistake indicating you didn't understand polymorphism or it doesn't really help the situation.
In this case I suspect the latter.

Local Variable / Class variable increment

So essentially what my program does is read in a data stream of words, and count the occurrence of each word, and the total number of unique words. It will will read them into a map. My program works perfectly except for one problem...when I call p.print(), the value for total is still at 0. There seems to be some problem where total is incremented in the for_each statement, but when I p.print, it acts as if was never incremented...My print function is defined as follows:
void print_words(const map<string,int> &aMap) {
PRN p(aMap.size());
for_each(aMap.begin(), aMap.end(), p);
p.print();
}
I have a class that is in charge of processing each word, here is the definition:
//CLASS PRN FUNCTIONS
// constructor
PRN::PRN(const int& s, const int& c, const int& t) {
sz=s;
cnt=c;
total=t;
}
// overloaded operator, where P is defined as
// typedef pair < string, int > P;
void PRN::operator()(const P& p) {
if(cnt%NO_ITEMS == 0 && cnt != 0)
cout << '\n';
cout << setw(ITEM_W) << left << p.first << " : " << setw(NO_W) << left << p.second;
total += p.second;
cnt++;
}
// to printout final value of total
void PRN::print() const {
cout << '\n' << '\n';
cout << "no of words in input stream : " << total << endl;
cout << "no of words in output stream : " << sz << endl;
}
Figured it out...I need to have
p = for_each(aMap.begin(), aMap.end(), p);
No better feeling then figuring out your own problem!