PPP2 Chapter 17 Exercise 11

Pages: 1... 1011121314... 16
The "this" pointer points to the object that a member function has been called on, and prev and succ are the previous and next pointers which point to the previous and next node, respectively. How do I not understand their importance?

I was saying to use a destructor because I thought maybe it'd be needed. And I don't need to call it myself since the compiler does that on its own.

I thought I'd need to call erase() again on the head node and trav.

I just said I don't know how to see the stack trace in the debugger. And it's also not giving me any ideas on where to call delete.

Edit: I don't know how to "delete" individual Link objects. I think that's what I'll need to do here.

For now, I've taken away dynamic memory to be safe. Here's the code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
int main()
{
	try
	{
		Link *gods;

		Link Odin{ { "Odin", "Norse",
			"Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		Link Baldr{ { "Baldr", "Norse", "Ship called Hringorni", "None" } };
		Link Thor{ { "Thor", "Norse",
			"Chariot pulled by goats Tanngrisnir and Tanngnjostr", "Hammer called Mjolnir" } };
		Link Frejya{ { "Frejya", "Norse",
			"Chariot pulled by two cats", "Magic called seidr" } };
		Link Ares{ { "Ares", "Greek", "War chariot", "Sword and spear" } };
		Link Zeus{ { "Zeus", "Greek",
			"A chariot pulled by the four major winds shaped as horses", "Thunderbolt" } };
		Link Apollo{ { "Apollo", "Greek",
			"Chariot pulled by the four horses Aethon, Pyrois, Phlegon and Eous", "A bow" } };
		Link Hera{ { "Hera", "Greek", "A chariot drawn by peacocks", "Her intelligence" } };
		Link Amaterasu{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } };
		Link Susanoo{ { "Susanoo", "Japanese", "", "Sword of Totsuka" } };
		Link Izanagi{ { "Izanagi", "Japanese", "", "Sword of Totsuka (later given to Susanoo)" } };
		Link Bishamonten{ { "Bishamonten", "Japanese", "", "A spear" } };

		gods = &Odin;
		gods = gods->add_ordered(&Baldr);
		gods = gods->add_ordered(&Thor);
		gods = gods->add_ordered(&Frejya);
		gods = gods->add_ordered(&Ares);
		gods = gods->add_ordered(&Zeus);
		gods = gods->add_ordered(&Apollo);
		gods = gods->add_ordered(&Hera);
		gods = gods->add_ordered(&Amaterasu);
		gods = gods->add_ordered(&Susanoo);
		gods = gods->add_ordered(&Izanagi);
		gods = gods->add_ordered(&Bishamonten);

		print_all(gods);

		Link *trav = gods;
		while (trav->previous() != nullptr)
		{
			trav = trav->previous();
		}
	}
	catch (const std::runtime_error &rte)
	{
		std::cerr << "Runtime error: " << rte.what() << '\n';
		keep_window_open();
		return 1;
	}
	catch (const std::exception &e)
	{
		std::cerr << "Exception: " << e.what() << "\n";
		keep_window_open();
		return 2;
	}
	catch (...)
	{
		std::cerr << "An unknown exception occurred\n";
		keep_window_open();
		return 3;
	}

	keep_window_open();
}


I'll try to move the gods to three different lists now.
Last edited on
The "this" pointer points to the object that a member function has been called on, and prev and succ are the previous and next pointers which point to the previous and next node, respectively. How do I not understand their importance?

So you know where the pointers are pointing, that doesn't mean anything about their importance. What happens to each of those pointers, especially the this pointer, in erase() is the question you don't seem to truly understand. Try calling erase() on any one of the Links in your current main, then examine all of the pointers in each of the Links. Is it possible using the Links remaining in the List to find and print the contents of the erased Link?

I was saying to use a destructor because I thought maybe it'd be needed. And I don't need to call it myself since the compiler does that on its own.

Why would a destructor be needed? The purpose of a destructor is to safely destroy resources owned by the class. In this class what resoruces are owned by the class?


I thought I'd need to call erase() again on the head node and trav.

Why? What is the "head" node?

I just said I don't know how to see the stack trace in the debugger.

Then you need to find and study some documentation and or a tutorial on your debugger. Your debugger is an essential tool that you need to learn to use.

And it's also not giving me any ideas on where to call delete.

Why would you think the debugger would give you any ideas on where to call delete. It is your job as a program designer to decide when you're done with the memory you manually allocated.

Edit: I don't know how to "delete" individual Link objects.

Then maybe you need to experiment with a more basic program that uses dynamic memory, one that just uses a Plain Old Data (POD) type. That manually allocates the memory, uses the memory, then deletes the memory when finished. Then possibly move on to an array of some POD type, doing the same.

For now, I've taken away dynamic memory to be safe.

Yea, punting is probably the best. No sense of learning how to safely handle manual memory, after all you'll probably never need to properly use dynamic memory anyway, right?

I'll try to move the gods to three different lists now.

Well since you've already done this, it should be easy.


Okay, I don't get it. I tried it like it is in the book, but it's not working.

Here's my code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
Link *gods;

Link Odin{ { "Odin", "Norse",
	"Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
Link Baldr{ { "Baldr", "Norse", "Ship called Hringorni", "None" } };
Link Thor{ { "Thor", "Norse",
	"Chariot pulled by goats Tanngrisnir and Tanngnjostr", "Hammer called Mjolnir" } };
Link Frejya{ { "Frejya", "Norse",
	"Chariot pulled by two cats", "Magic called seidr" } };
Link Ares{ { "Ares", "Greek", "War chariot", "Sword and spear" } };
Link Zeus{ { "Zeus", "Greek",
	"A chariot pulled by the four major winds shaped as horses", "Thunderbolt" } };
Link Apollo{ { "Apollo", "Greek",
	"Chariot pulled by the four horses Aethon, Pyrois, Phlegon and Eous", "A bow" } };
Link Hera{ { "Hera", "Greek", "A chariot drawn by peacocks", "Her intelligence" } };
Link Amaterasu{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } };
Link Susanoo{ { "Susanoo", "Japanese", "", "Sword of Totsuka" } };
Link Izanagi{ { "Izanagi", "Japanese", "", "Sword of Totsuka (later given to Susanoo)" } };
Link Bishamonten{ { "Bishamonten", "Japanese", "", "A spear" } };

gods = &Odin;
gods = gods->add_ordered(&Baldr);
gods = gods->add_ordered(&Thor);
gods = gods->add_ordered(&Frejya);
gods = gods->add_ordered(&Ares);
gods = gods->add_ordered(&Zeus);
gods = gods->add_ordered(&Apollo);
gods = gods->add_ordered(&Hera);
gods = gods->add_ordered(&Amaterasu);
gods = gods->add_ordered(&Susanoo);
gods = gods->add_ordered(&Izanagi);
gods = gods->add_ordered(&Bishamonten);

Link *norse_gods = nullptr;
//Link *greek_gods;
//Link *jap_gods;
Link *trav = gods->find("Odin");
if (trav)
{
	std::cout << "trav is not null\n";
	if (trav == gods)
	{
		gods = trav->next();
	}
	trav = trav->erase();
	norse_gods = norse_gods->add_ordered(trav);
}
if (norse_gods)
{
	print_all(norse_gods);
}
else
{
	std::cout << "Whoops, something's wrong\n";
}


And this is how it is in the book (note that I also tried it by doing trav->erase() like in the book, but norse_gods is still null):
1
2
3
4
5
6
Link* p2 = norse_gods–>find("Zeus");
if (p2) {
    if (p2==norse_gods) norse_gods = p2–>next();
    p2–>erase();
    greek_gods = greek_gods–>insert(p2);
}


This was when he'd deliberately put Zeus in the wrong pantheon to show how to fix the "mistake".

For some reason, trav isn't null so the code inside that check did run, but norse_gods is still null when I try to print it after that.
Last edited on
I hadn't seen your post until just now. Sorry about that.

I tried to do the thing from earlier in the book where he moves Zeus into the correct list for his pantheon, and in that scenario it worked correctly. But when I try it when it's like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
God *pOdin = new God{ "Odin", "Norse",
			"Eight-legged flying horse called Sleipnir", "Spear called Gungnir" };
God *pBaldr = new God{ "Baldr", "Norse", "Ship called Hringorni", "None" };
God *pThor = new God{ "Thor", "Norse",
			"Chariot pulled by goats Tanngrisnir and Tanngnjostr", "Hammer called Mjolnir" };
God *pFrejya = new God{ "Frejya", "Norse",
			"Chariot pulled by two cats", "Magic called seidr" };
God *pAres = new God{ "Ares", "Greek", "War chariot", "Sword and spear" };
God *pZeus = new God{ "Zeus", "Greek",
			"A chariot pulled by the four major winds shaped as horses", "Thunderbolt and the shield called Aegis" };
God *pApollo = new God{ "Apollo", "Greek",
			"Chariot pulled by the four horses Aethon, Pyrois, Phlegon and Eous", "A bow" };
God *pHera = new God{ "Hera", "Greek", "A chariot drawn by peacocks", "Her intelligence" };
God *pAthena = new God{ "Athena", "Greek", "", "Allowed to use Zeus's Thunderbolt and Aegis" };
God *pPoseidon = new God{ "Poseidon", "Greek", "A chariot pulled either by a hippocampus or by four horses that can ride on the seas",
			"A three-pronged spear called Trident" };
God *pAmaterasu = new God{ "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" };
God *pSusanoo = new God{ "Susanoo", "Japanese", "", "Sword of Totsuka" };
God *pIzanagi = new God{ "Izanagi", "Japanese", "", "Sword of Totsuka (later given to Susanoo)" };
God *pBishamonten = new God{ "Bishamonten", "Japanese", "", "A spear" };

Link *Odin = new Link{ pOdin };
Link *Baldr = new Link{ pBaldr };
Link *Thor = new Link{ pThor };
Link *Frejya = new Link{ pFrejya };
Link *Ares = new Link{ pAres };
Link *Zeus = new Link{ pZeus };
Link *Apollo = new Link{ pApollo };
Link *Hera = new Link{ pHera };
Link *Amaterasu = new Link{ pAmaterasu };
Link *Susanoo = new Link{ pSusanoo };
Link *Izanagi = new Link{ pIzanagi };
Link *Bishamonten = new Link{ pBishamonten };
Link *Athena = new Link{ pAthena };
Link *Poseidon = new Link{ pPoseidon };
		
Link *gods = Odin;
gods = gods->add_ordered(Thor);
gods = gods->add_ordered(Baldr);
gods = gods->add_ordered(Frejya);
gods = gods->add_ordered(Zeus);
gods = gods->add_ordered(Hera);
gods = gods->add_ordered(Athena);
gods = gods->add_ordered(Poseidon);
gods = gods->add_ordered(Apollo);
gods = gods->add_ordered(Ares);
gods = gods->add_ordered(Amaterasu);
gods = gods->add_ordered(Susanoo);
gods = gods->add_ordered(Izanagi);
gods = gods->add_ordered(Bishamonten);

// code for moving will go here when added back in

delete Odin;
Odin = nullptr;
delete Thor;
Thor = nullptr;
delete Baldr;
Baldr = nullptr;
delete Frejya;
Frejya = nullptr;
delete Zeus;
Zeus = nullptr;
delete Hera;
Hera = nullptr;
delete Athena;
Athena = nullptr;
delete Ares;
Ares = nullptr;
delete Apollo;
Apollo = nullptr;
delete Poseidon;
Poseidon = nullptr;
delete Amaterasu;
Amaterasu = nullptr;
delete Susanoo;
Susanoo = nullptr;
delete Bishamonten;
Bishamonten = nullptr;
delete Izanagi;
Izanagi = nullptr;
delete pOdin;
pOdin = nullptr;
delete pThor;
pThor = nullptr;
delete pBaldr;
pBaldr = nullptr;
delete pFrejya;
pFrejya = nullptr;
delete pZeus;
pZeus = nullptr;
delete pHera;
pHera = nullptr;
delete pAthena;
pAthena = nullptr;
delete pAres;
pAres = nullptr;
delete pApollo;
pApollo = nullptr;
delete pPoseidon;
pPoseidon = nullptr;
delete pAmaterasu;
pAmaterasu = nullptr;
delete pSusanoo;
pSusanoo = nullptr;
delete pBishamonten;
pBishamonten = nullptr;
delete pIzanagi;
pIzanagi = nullptr;


It doesn't work. When I tried to call print_all() when norse_gods and gods weren't null, print_all() didn't get called. Did initialize the gods incorrectly?

I saw that I couldn't do anything to the God class's objects through the Link class, so I made m_god in the Link class a pointer.

If I do it like in the book with the dynamic memory, it'll work. But then I wouldn't know how to free all the Link objects allocated by the gods object. Just calling delete on gods doesn't work because it still leaves memory behind to leak. Having separate named Gods and Links is better for freeing of resources, but that seems to be making harder to move them between lists unless I'm just doing it wrong.
Last edited on
I'll ask this here, then: how do I delete an anonymous object of a class that doesn't own the allocated memory? I tried searching around on the web, but I haven't been able to find anything useful yet.

Do I have to assign the anonymous Link objects to a named object to delete it?
It sure would be nice if you ever gave proper debugging a try. The results you're getting now are the results you should expect when you just throw a bunch of garbage against the wall to see what sticks. I'm not going to comment further on your latest mess I suggest you back track and try again.

From your previous post:
Okay, I don't get it. I tried it like it is in the book, but it's not working.


What exactly is not working?

Do the gods get properly added to the gods "List"?

Or is something else wrong?

And this is how it is in the book (note that I also tried it by doing trav->erase() like in the book, but norse_gods is still null):


Did you double check the books code against yours? Are they the same (except for the name changes)?

Your "move" code does seem to differ from the books code, IMO.

Did you double check your add() and insert() code against the code in the book, are they both the same as well?


The insert() function was the only one shown in the book as a member function after the change to rely on the this pointer was made. I had to update add() myself. I'm sure it's how it should be, though, since it does work as expected.

I do need to know how to delete anonymous members of a class that were dynamically allocated since I don't know how to do that. Debugging isn't really going to help if I don't even have any idea what the "correct" code should be, is it?

I'll get back to just anonymous objects first, except with the God struct being nested inside the Link class, and then get back to you on these questions:
What exactly is not working?

Do the gods get properly added to the gods "List"?

Or is something else wrong?


I have an infinite loop in find(). The trav and m_succ pointers are both pointing at the Frejya node after a while, and it just stays that way for a long time.

Classes:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
struct God
{
	God(const std::string &name, const std::string &myth, const std::string &vehicle, const std::string &weapon)
		: m_name{ name }, m_myth{ myth }, m_vehicle{ vehicle }, m_weapon{ weapon } { }

	std::string name() const { return m_name; }
	std::string myth() const { return m_myth; }
	std::string vehicle() const { return m_vehicle; }
	std::string weapon() const { return m_weapon; }
private:
	std::string m_name;
	std::string m_myth;
	std::string m_vehicle;
	std::string m_weapon;
};

class Link
{
public:
	Link(God *god, Link *p = nullptr, Link *s = nullptr)
		: m_god{ god }, m_prev{ p }, m_succ{ s } { }
	~Link()
	{
		delete m_god;
	}

	Link *insert(Link *n);                                            // insert n before this object
	Link *add(Link *n);                                               // insert n after this object
	Link *erase();                                                    // remove this object from list
	Link *find(const std::string &name);                              // find node matching passed in name in list
	const Link *find(const std::string &name) const;                  // find node matching passed in name in const list
	Link *find_if_myth(const std::string &myth);		              // find node matching passsed in myth in list
	const Link *find_if_myth(const std::string &myth) const;          // find node matching passsed in myth in const list
	Link *advance(int n) const;                                       // advance n positions in list
	Link *add_ordered(Link *n);							              // insert n in its correct lexicographical position

	God *god() const { return m_god; }
	Link *next() const { return m_succ; }
	Link *previous() const { return m_prev; }
private:
	God *m_god;
	Link *m_prev;
	Link *m_succ;
};


main():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
int main()
{
	try
	{	
		Link Odin{ new God{ "Odin", "Norse", "Eight-legged flying horse called Sleipnir",  "Spear called Gungnir" } };
		Link Thor{ new God{ "Thor", "Norse", "Chariot pulled by goats Tanngrisnir and Tanngnjostr", "Hammer called Mjolnir" } };
		Link Baldr{ new God{ "Baldr", "Norse", "A giant ship called Hringorni", "None" } };
		Link Frejya{ new God{ "Frejya", "Norse", "Chariot pulled by two cats", "Magic called seidr" } };
		Link Ares{ new God{ "Ares", "Greek", "War chariot", "Sword and spear" } };
		Link Zeus{ new God{ "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses", 
			"Thunderbolt and the shield called Aegis" } };
		Link Apollo{ new God{ "Apollo", "Greek", "Chariot pulled by the four horses Aethon, Pyrois, Phlegon and Eous", "A bow" } };
		Link Hera{ new God{ "Hera", "Greek", "A chariot drawn by peacocks", "Her intelligence" } };
		Link Athena{ new God{ "Athena", "Greek", "", "Allowed to use Zeus's Thunderbolt and Aegis" } };
		Link Poseidon{ new God{ "Poseidon", "Greek",
			"A chariot pulled either by a hippocampus or by four horses that can ride on the seas", "A three-pronged spear called Trident" } };
		Link Amaterasu{ new God{ "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } };
		Link Susanoo{ new God{ "Susanoo", "Japanese", "", "Sword of Totsuka" } };
		Link Izanagi{ new God{ "Izanagi", "Japanese", "", "Sword of Totsuka (later given to Susanoo)" } };
		Link Bishamonten{ new God{ "Bishamonten", "Japanese", "", "A spear" } };
		
		Link *gods = &Odin;
		gods = gods->add_ordered(&Thor);
		gods = gods->add_ordered(&Baldr);
		gods = gods->add_ordered(&Frejya);
		gods = gods->add_ordered(&Ares);
		gods = gods->add_ordered(&Zeus);
		gods = gods->add_ordered(&Apollo);
		gods = gods->add_ordered(&Hera);
		gods = gods->add_ordered(&Athena);
		gods = gods->add_ordered(&Poseidon);
		gods = gods->add_ordered(&Amaterasu);
		gods = gods->add_ordered(&Susanoo);
		gods = gods->add_ordered(&Izanagi);
		gods = gods->add_ordered(&Bishamonten);

		Link *norse_gods = &Odin;
		Link *greek_gods = &Zeus;
		Link *jap_gods = &Amaterasu;
		Link *trav = gods->find("Odin");
		if (trav)
		{
			if (trav == gods)
			{
				trav = gods->next();
			}
			trav->erase();
			trav = norse_gods->find("Odin");
			if (!trav)
			{
				norse_gods = norse_gods->add_ordered(trav);
			}
		}
		std::cout << "gods list:\n";
		print_all(gods);
		std::cout << "\nnorse_gods list:\n";
		print_all(norse_gods);
		std::cout << '\n';
	}
	catch (const std::runtime_error &rte)
	{
		std::cerr << "Runtime error: " << rte.what() << '\n';
		keep_window_open();
		return 1;
	}
	catch (const std::exception &e)
	{
		std::cerr << "Exception: " << e.what() << "\n";
		keep_window_open();
		return 2;
	}
	catch (...)
	{
		std::cerr << "An unknown exception occurred\n";
		keep_window_open();
		return 3;
	}

	keep_window_open();
}


Update:
The infinite loop is still there, but either way, I've changed it back to pretty much what it was at first, except for the m_god member being a pointer that's being allocated in during initialization and being deleted in the destructor.

Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
int main()
{
	try
	{	
		Link *gods = new Link{ new God{ "Odin", "Norse", 
			"Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		gods = gods->add_ordered(new Link{ new God{ "Thor", "Norse", 
			"Chariot pulled by goats Tanngrisnir and Tanngnjostr", "Hammer called Mjolnir" } });
		gods = gods->add_ordered(new Link{ new God{ "Baldr", "Norse", "A giant ship called Hringorni", "None" } });
		gods = gods->add_ordered(new Link{ new God{ "Frejya", "Norse", "Chariot pulled by two cats", "Magic called seidr" } });
		gods = gods->add_ordered(new Link{ new God{ "Ares", "Greek", "War chariot", "Sword and spear" } });
		gods = gods->add_ordered(new Link{ new God{ "Zeus", "Greek", 
			"A chariot pulled by the four major winds shaped as horses", "Thunderbolt and the shield called Aegis" } });
		gods = gods->add_ordered(new Link{ new God{ "Apollo", "Greek", 
			"Chariot pulled by the four horses Aethon, Pyrois, Phlegon and Eous", "A bow" } });
		gods = gods->add_ordered(new Link{ new God{ "Hera", "Greek", "A chariot drawn by peacocks", "Her intelligence" } });
		gods = gods->add_ordered(new Link{ new God{ "Poseidon", "Greek",
			"A chariot pulled either by a hippocampus or by four horses that can ride on the seas", "A three-pronged spear called Trident" } });
		gods = gods->add_ordered(new Link{ new God{ "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } });
		gods = gods->add_ordered(new Link{ new God{ "Susanoo", "Japanese", "", "Sword of Totsuka" } });
		gods = gods->add_ordered(new Link{ new God{ "Izanagi", "Japanese", "", "Sword of Totsuka (later given to Susanoo)" } });
		gods = gods->add_ordered(new Link{ new God{ "Bishamonten", "Japanese", "", "A spear" } });

		Link *norse_gods = new Link{ new God{ "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		Link *greek_gods = new Link{ new God{ "Ares", "Greek", "War chariot", "Sword and spear" } };
		Link *jap_gods = new Link{ new God{ "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } };

		Link *trav = gods->find("Odin");
		if (trav)
		{
			if (trav == gods)
			{
				gods = trav->next();
			}
			trav->erase();
			trav = norse_gods->find("Odin");
			if (!trav)
			{
				norse_gods = norse_gods->add_ordered(trav);
			}
		}
		std::cout << "gods list:\n";
		print_all(gods);
		std::cout << "\nnorse_gods list:\n";
		print_all(norse_gods);
		std::cout << '\n';
	}
	catch (const std::runtime_error &rte)
	{
		std::cerr << "Runtime error: " << rte.what() << '\n';
		keep_window_open();
		return 1;
	}
	catch (const std::exception &e)
	{
		std::cerr << "Exception: " << e.what() << "\n";
		keep_window_open();
		return 2;
	}
	catch (...)
	{
		std::cerr << "An unknown exception occurred\n";
		keep_window_open();
		return 3;
	}

	keep_window_open();
}


I added the named pointers I have in main() to the watch in the debugger to try to see what's happening to them, but I can't see much since it goes to call find() on line 89 on my code (line 40 in what I've shown here), and then gets stuck in an infinite loop when it gets to Frejya.
Last edited on
Okay, I tried to change the code to use std::unique_ptr instead of a raw pointer and updated print_all() (without doing anything to the rest of the code, except main()).

This is my current main():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
int main()
{
	try
	{
		std::unique_ptr<Link> gods = std::make_unique<Link>(new Link{ new God{ "Odin", "Norse",
			"Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } });
		gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Thor", "Norse",
			"Chariot pulled by goats Tanngrisnir and Tanngnjostr", "Hammer called Mjolnir" } })));
		gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Baldr", "Norse", 
			"A giant ship called Hringorni", "None" } })));
		gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Frejya", "Norse", 
			"Chariot pulled by two cats", "Magic called seidr" } })));
		gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Ares", "Greek", 
			"War chariot", "Sword and spear" } })));
		gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Zeus", "Greek",
			"A chariot pulled by the four major winds shaped as horses", "Thunderbolt and the shield called Aegis" } })));
		gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Apollo", "Greek",
			"Chariot pulled by the four horses Aethon, Pyrois, Phlegon and Eous", "A bow" } })));
		gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Hera", "Greek",
			"A chariot drawn by peacocks", "Her intelligence" } })));
		gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Poseidon", "Greek",
			"A chariot pulled either by a hippocampus or by four horses that can ride on the seas", 
			"A three-pronged spear called Trident" } })));
		gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Athena", "Greek", "", 
			"Allowed to use Zeus's Thunderbolt and the Aegis" } })));
		gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Amaterasu", "Japanese", "", 
			"Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } })));
		gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Susanoo", "Japanese", "", "Sword of Totsuka" } })));
		gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Izanagi", "Japanese", "", 
			"Sword of Totsuka (later given to Susanoo)" } })));
		gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Bishamonten", "Japanese", "", "A spear" } })));

		std::unique_ptr<Link> norse_gods = std::make_unique<Link>(new Link{ new God{ "Odin", "Norse",
			"Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } });
		std::unique_ptr<Link> greek_gods = std::make_unique<Link>(new Link{ new God{ "Zeus", "Greek",
			"A chariot pulled by the four major winds shaped as horses", "Thunderbolt and the shield called Aegis" } });
		std::unique_ptr<Link> jap_gods = std::make_unique<Link>(new Link{ new God{ "Amaterasu", "Japanese", "",
			"Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } });

		std::unique_ptr<Link> trav = std::make_unique<Link>(std::move(gods->find("Odin")));
		if (trav)
		{
			if (trav == gods)
			{
				gods = std::make_unique<Link>(std::move(trav->next()));
			}
			trav->erase();
		}
		std::cout << "gods list:\n";
		print_all(gods);
	}
	catch (const std::runtime_error &rte)
	{
		std::cerr << "Runtime error: " << rte.what() << '\n';
		keep_window_open();
		return 1;
	}
	catch (const std::bad_alloc &ba)
	{
		std::cerr << "Bad allocation error: " << ba.what() << '\n';
		keep_window_open();
		return 2;
	}
	catch (const std::exception &e)
	{
		std::cerr << "Exception: " << e.what() << "\n";
		keep_window_open();
		return 3;
	}
	catch (...)
	{
		std::cerr << "An unknown exception occurred\n";
		keep_window_open();
		return 4;
	}

	keep_window_open();
}


But this won't compile. I get this error message:
1>linked_list.cpp(67,37) : note: in instantiation of function template specialization 'std::make_unique<Link, Link *, void>' requested here


It's talking about the first line inside the try block.

This is print_all(), by the way:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void print_all(std::unique_ptr<Link> &p)
{
	if (p->previous() != nullptr)
	{
		while (p->previous() != nullptr)
		{
			p = std::make_unique<Link>(std::move(p->previous()));
		}
	}

	std::cout << "{\n";
	while (p)
	{
		std::cout << "Name: " << p->god()->name()
			<< "; Myth: " << p->god()->myth();
		if (p->god()->vehicle() != "")
		{
			std::cout << "; Vehicle: " << p->god()->vehicle();
		}
		else
		{
			std::cout << "; Vehicle: N/A";
		}
		std::cout << "; Weapon: " << p->god()->weapon();
		if ((p = std::make_unique<Link>(std::move(p->next()))))
		{
			std::cout << "\n";
		}
	}
	std::cout << "\n}\n";
}
Last edited on
New updated code:
main():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
int main()
{
	try
	{
		Link *gods = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		gods = gods->add_ordered(new Link{ { "Thor", "Norse", "Chariot pulled by goats Tanngrisnir and Tanngnjostr",
			"Hammer called Mjolnir" } });
		gods = gods->add_ordered(new Link{ { "Baldr", "Norse", "A giant ship called Hringorni", "None" } });
		gods = gods->add_ordered(new Link{ { "Frejya", "Norse", "Chariot pulled by two cats", "Magic called seidr" } });
		gods = gods->add_ordered(new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
			"Thunderbolt and the shield called Aegis" } });
		gods = gods->add_ordered(new Link{ { "Hera", "Greek", "A chariot drawn by peacocks", "Her intelligence" } });
		gods = gods->add_ordered(new Link{ { "Athena", "Greek", "", "Allowed to use Zeus's Thunderbolt and the Aegis" } });
		gods = gods->add_ordered(new Link{ { "Ares", "Greek", "War chariot", "Sword and spear" } });
		gods = gods->add_ordered(new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } });
		gods = gods->add_ordered(new Link{ { "Susanoo", "Japanese", "", "Sword of Totsuka" } });
		gods = gods->add_ordered(new Link{ { "Izanagi", "Japanese", "", "Sword of Totsuka (later given to Susanoo)" } });
		gods = gods->add_ordered(new Link{ { "Bishamonten", "Japanese", "", "A spear" } });

		Link Odin{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		Link Zeus{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
			"Thunderbolt and the shield called Aegis" } };
		Link Amaterasu{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } };

		Link *norse_gods = &Odin;
		Link *greek_gods = &Zeus;
		Link *jap_gods = &Amaterasu;

		Link *trav = gods->find("Odin");
		if (trav)
		{
			if (trav == gods)
			{
				gods = trav->next();
			}
			trav->erase();
			trav = norse_gods->find("Odin");
			if (!trav)
			{
				norse_gods = norse_gods->add_ordered(trav);
			}
		}
		trav = gods->find("Thor");
		if (trav)
		{
			if (trav == gods)
			{
				gods = trav->next();
			}
			trav->erase();
			norse_gods = norse_gods->add_ordered(trav);
		}
		trav = gods->find("Baldr");
		if (trav)
		{
			if (trav == gods)
			{
				gods = trav->next();
			}
			trav->erase();
			norse_gods = norse_gods->add_ordered(trav);
		}
		trav = gods->find("Frejya");
		if (trav)
		{
			if (trav == gods)
			{
				gods = trav->next();
			}
			trav->erase();
			norse_gods = norse_gods->add_ordered(trav);
		}
		trav = gods->find("Zeus");
		if (trav)
		{
			if (trav == gods)
			{
				gods = trav->next();
			}
			trav->erase();
			trav = greek_gods->find("Zeus");
			if (!trav)
			{
				greek_gods = greek_gods->add_ordered(trav);
			}
		}
		trav = gods->find("Hera");
		if (trav)
		{
			if (trav == gods)
			{
				gods = trav->next();
			}
			trav->erase();
			greek_gods = greek_gods->add_ordered(trav);
		}
		trav = gods->find("Athena");
		if (trav)
		{
			if (trav == gods)
			{
				gods = trav->next();
			}
			trav->erase();
			greek_gods = greek_gods->add_ordered(trav);
		}
		trav = gods->find("Ares");
		if (trav)
		{
			if (trav == gods)
			{
				gods = trav->next();
			}
			trav->erase();
			greek_gods = greek_gods->add_ordered(trav);
		}
		trav = gods->find("Amaterasu");
		if (trav)
		{
			if (trav == gods)
			{
				gods = trav->next();
			}
			trav->erase();
			trav = jap_gods->find("Amaterasu");
			if (!trav)
			{
				jap_gods = jap_gods->add_ordered(trav);
			}
		}
		trav = gods->find("Susanoo");
		if (trav)
		{
			if (trav == gods)
			{
				gods = trav->next();
			}
			trav->erase();
			jap_gods = jap_gods->add_ordered(trav);
		}
		trav = gods->find("Izanagi");
		if (trav)
		{
			if (trav == gods)
			{
				gods = trav->next();
			}
			trav->erase();
			jap_gods = jap_gods->add_ordered(trav);
		}
		trav = gods->find("Bishamonten");
		if (trav)
		{
			if (trav == gods)
			{
				gods = trav->next();
			}
			trav->erase();
			jap_gods = jap_gods->add_ordered(trav);
		}
		std::cout << "gods list:\n";
		print_all(gods);
		std::cout << "\nnorse_gods list:\n";
		print_all(norse_gods);
		std::cout << "\ngreek_gods list:\n";
		print_all(greek_gods);
		std::cout << "\njap_gods list:\n";
		print_all(jap_gods);
	}
	catch (const std::runtime_error &rte)
	{
		std::cerr << "Runtime error: " << rte.what() << '\n';
		keep_window_open();
		return 1;
	}
	catch (const std::bad_alloc &ba)
	{
		std::cerr << "Bad allocation error: " << ba.what() << '\n';
		keep_window_open();
		return 2;
	}
	catch (const std::exception &e)
	{
		std::cerr << "Exception: " << e.what() << "\n";
		keep_window_open();
		return 3;
	}
	catch (...)
	{
		std::cerr << "An unknown exception occurred\n";
		keep_window_open();
		return 4;
	}

	keep_window_open();
}


Link and God class definitions:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
struct God
	{
		God(const std::string &name, const std::string &myth, const std::string &vehicle, const std::string &weapon)
			: m_name{ name }, m_myth{ myth }, m_vehicle{ vehicle }, m_weapon{ weapon } { }
		God()
			: m_name{}, m_myth{}, m_vehicle{}, m_weapon{} {}

		std::string m_name;
		std::string m_myth;
		std::string m_vehicle;
		std::string m_weapon;
	};

class Link
{
public:
	Link(const God &god, Link *p = nullptr, Link *n = nullptr)
		: m_god{ god }, m_prev{ p }, m_succ{ n }
	{	
	}

	Link *insert(Link *n);                                            // insert n before this object
	Link *add(Link *n);                                               // insert n after this object
	Link *erase();                                                    // remove this object from list
	Link *find(const std::string &name);                              // find node matching passed in name in list
	const Link *find(const std::string &name) const;                  // find node matching passed in name in const list
	Link *advance(int n) const;                                       // advance n positions in list
	Link *add_ordered(Link *n);                                       // insert n in its correct lexicographical position

	God god() const { return m_god; }
	Link *next() const { return m_succ; }
	Link *previous() const { return m_prev; }
private:
	God m_god;
	Link *m_prev;
	Link *m_succ;
};


I still have that problem of an infinite loop occurring in find(). I don't know why that's happening. And how do I free memory that's dynamically allocated for anonymous objects? And if I put "new" in the constructor and "delete" in the destructor, and also add pointer in the Link class that gets initialized with "new" when arguments are passed in the constructor, how should I initialize a Link in main()? I shouldn't call new in main(), right? So what should I do? What I did try (like using the address-of operator on named non-pointer Link objects) gave me a stack overflow error when I also had new and delete in the constructor and destructor.
I still have that problem of an infinite loop occurring in find(). I don't know why that's happening.

Perhaps you should look at your pointers and see what they look like, then maybe you might be able to see some problem with your logic in your find() function.

And how do I free memory that's dynamically allocated for anonymous objects?

I don't know what you're asking here. I don't see any anonymous objects being manually allocated memory.

I really think you should worry about getting your "move" working properly and worrying about freeing the memory later. You do realize that you should be "moving" based on Myth not the god's name, right?

That's what I'm doing, though. I'm moving the gods to their correct myth lists.

All of my Links in main() are being allocated memory dynamically, aren't they? And aside from the lists themselves, none of the Link objects are named. So I'm asking about how to free that memory. Look here:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Link *gods = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		gods = gods->add_ordered(new Link{ { "Thor", "Norse", "Chariot pulled by goats Tanngrisnir and Tanngnjostr",
			"Hammer called Mjolnir" } });
		gods = gods->add_ordered(new Link{ { "Baldr", "Norse", "A giant ship called Hringorni", "None" } });
		gods = gods->add_ordered(new Link{ { "Frejya", "Norse", "Chariot pulled by two cats", "Magic called seidr" } });
		gods = gods->add_ordered(new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
			"Thunderbolt and the shield called Aegis" } });
		gods = gods->add_ordered(new Link{ { "Hera", "Greek", "A chariot drawn by peacocks", "Her intelligence" } });
		gods = gods->add_ordered(new Link{ { "Athena", "Greek", "", "Allowed to use Zeus's Thunderbolt and the Aegis" } });
		gods = gods->add_ordered(new Link{ { "Ares", "Greek", "War chariot", "Sword and spear" } });
		gods = gods->add_ordered(new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } });
		gods = gods->add_ordered(new Link{ { "Susanoo", "Japanese", "", "Sword of Totsuka" } });
		gods = gods->add_ordered(new Link{ { "Izanagi", "Japanese", "", "Sword of Totsuka (later given to Susanoo)" } });
		gods = gods->add_ordered(new Link{ { "Bishamonten", "Japanese", "", "A spear" } });


Isn't that dynamic memory being allocated for anonymous objects? Those Links don't have names, aside from the actual list itself (gods).

Anyway, are you saying there's a problem with my pointers in find()? I'll try to see if I can find it, then. But a hint as to what I should look for might be helpful.

By the way, if I do this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Link
{
public:
    Link(const God &god, Link *p = nullptr, Link *s = nullptr)
        : m_god{god}, m_prev{p}, m_succ{s} 
    {
        m_link = new Link{m_god, m_prev, m_succ};
    }
    ~Link()
    {
        delete m_link;
    }
private:
    God m_god;
    Link *m_link;
    Link *m_prev;
    Link *m_succ;
};


How should I initialize the Link objects in main()? I shouldn't manually use "new" in main() with the Link class's constructor and destructor like that, right?

Edit: I've taken care of the infinite loop problem by fixing line 307, trav = trav->m_succ;, which is line 10 here:
1
2
3
4
5
6
7
8
9
10
11
12
13
Link *Link::find(const std::string &name)
{
	Link *trav = this;
	while (trav != nullptr)
	{
		if (trav->m_god.m_name == name)
		{
			return trav;
		}
		trav = trav->m_succ;
	}
	return this;
}


But now the this pointer in previous() is becoming null again, when I try to call print_all() on the gods list, on line 212 in main() (which is line 162 in the code I posted here). Is it because of misusing erase() again? Do I have to do something to the pointers in the list I use erase() on so that the places that are null won't be touched? It hit a nullptr while in the code in print_all() for going back to the head of the list if it's not already there.
Last edited on
I made these functions:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Link *Link::find_if_myth(const std::string &myth)
{
	Link *trav = this;
	while (trav != nullptr)
	{
		if (trav->m_god.m_myth == myth)
		{
			return trav;
		}
		trav = trav->m_succ;
	}
	return this;
}

const Link *Link::find_if_myth(const std::string &myth) const
{
	const Link *c_trav = this;                    // const pointer
	Link *nc_trav = const_cast<Link*>(c_trav);    // non-const pointer
	while (c_trav != nullptr && nc_trav != nullptr)
	{
		if (c_trav->m_god.m_myth == myth)
		{
			return c_trav;
		}
		nc_trav = nc_trav->m_succ;
	}
	return this;
}


And I did this just in case I end up trying to insert another copy of the node that's already in the list:
1
2
3
4
else if (n->m_god.m_name == trav->m_god.m_name)
{
	// do nothing
}


Would this be a good idea? I have another infinite loop in main(). Is it because of this? It happens after I insert Frejya into the norse_gods list, it seems, unless I misunderstood when it's happening exactly. All I really know for sure is that it's in the first loop I have in main(). Here:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
int main()
{
	try
	{
		Link *gods = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		gods = gods->add_ordered(new Link{ { "Thor", "Norse", "Chariot pulled by goats Tanngrisnir and Tanngnjostr",
			"Hammer called Mjolnir" } });
		gods = gods->add_ordered(new Link{ { "Baldr", "Norse", "A giant ship called Hringorni", "None" } });
		gods = gods->add_ordered(new Link{ { "Frejya", "Norse", "Chariot pulled by two cats", "Magic called seidr" } });
		gods = gods->add_ordered(new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
			"Thunderbolt and the shield called Aegis" } });
		gods = gods->add_ordered(new Link{ { "Hera", "Greek", "A chariot drawn by peacocks", "Her intelligence" } });
		gods = gods->add_ordered(new Link{ { "Athena", "Greek", "", "Allowed to use Zeus's Thunderbolt and the Aegis" } });
		gods = gods->add_ordered(new Link{ { "Ares", "Greek", "War chariot", "Sword and spear" } });
		gods = gods->add_ordered(new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } });
		gods = gods->add_ordered(new Link{ { "Susanoo", "Japanese", "", "Sword of Totsuka" } });
		gods = gods->add_ordered(new Link{ { "Izanagi", "Japanese", "", "Sword of Totsuka (later given to Susanoo)" } });
		gods = gods->add_ordered(new Link{ { "Bishamonten", "Japanese", "", "A spear" } });

		Link *Odin = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		Link *Zeus = new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
			"Thunderbolt and the shield called Aegis" } };
		Link *Amaterasu = new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } };

		Link *norse_gods = Odin;
		Link *greek_gods = Zeus;
		Link *jap_gods = Amaterasu;

		Link *trav = gods->find_if_myth("Norse");
		while (trav)
		{
			if (trav == gods)
			{
				trav = gods->next();
			}
			trav->erase();
			norse_gods = norse_gods->add_ordered(trav);
		}
		trav = gods->find_if_myth("Greek");
		while (trav)
		{
			if (trav == gods)
			{
				trav = gods->next();
			}
			trav->erase();
			greek_gods = greek_gods->add_ordered(trav);
		}
		trav = gods->find_if_myth("Japanese");
		while (trav)
		{
			if (trav == gods)
			{
				trav = gods->next();
			}
			trav->erase();
			jap_gods = jap_gods->add_ordered(trav);
		}

		std::cout << "gods list:\n";
		print_all(gods);
		std::cout << "\nnorse_gods list:\n";
		print_all(norse_gods);
		std::cout << "\ngreek_gods list:\n";
		print_all(greek_gods);
		std::cout << "\njap_gods list:\n";
		print_all(jap_gods);

		delete Odin;
		delete Zeus;
		delete Amaterasu;
		delete gods;
	}
	catch (const std::runtime_error &rte)
	{
		std::cerr << "Runtime error: " << rte.what() << '\n';
		keep_window_open();
		return 1;
	}
	catch (const std::bad_alloc &ba)
	{
		std::cerr << "Bad allocation error: " << ba.what() << '\n';
		keep_window_open();
		return 2;
	}
	catch (const std::exception &e)
	{
		std::cerr << "Exception: " << e.what() << "\n";
		keep_window_open();
		return 3;
	}
	catch (...)
	{
		std::cerr << "An unknown exception occurred\n";
		keep_window_open();
		return 4;
	}

	keep_window_open();
}
Last edited on
Isn't that dynamic memory being allocated for anonymous objects?

No.

Those Links don't have names, aside from the actual list itself (gods).

Who cares about names, the memory is being assigned to pointers.

Anyway, are you saying there's a problem with my pointers in find()?

I'm saying it's possible. You haven't shown the code that may be causing the problems so it's only a guess.

But a hint as to what I should look for might be helpful.

As a WAG look for a pointer that is orphaned or a nullptr.

By the way, if I do this:

Then as I have said previously you're trying to delete memory you don't own.

How should I initialize the Link objects in main()?

What's wrong with what you're currently doing the allocation?
Link *gods = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };

No new in the constructor required, therefor no delete required in a destructor. This class doesn't need to own that memory.





Okay, then you'll have to help me freeing the memory because I don't get how to do it in this kind of situation.

Anyway, how about the questions I asked here?
I made these functions:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Link *Link::find_if_myth(const std::string &myth)
{
	Link *trav = this;
	while (trav != nullptr)
	{
		if (trav->m_god.m_myth == myth)
		{
			return trav;
		}
		trav = trav->m_succ;
	}
	return this;
}

const Link *Link::find_if_myth(const std::string &myth) const
{
	const Link *c_trav = this;                    // const pointer
	Link *nc_trav = const_cast<Link*>(c_trav);    // non-const pointer
	while (c_trav != nullptr && nc_trav != nullptr)
	{
		if (c_trav->m_god.m_myth == myth)
		{
			return c_trav;
		}
		nc_trav = nc_trav->m_succ;
	}
	return this;
}


And I did this just in case I end up trying to insert another copy of the node that's already in the list:
1
2
3
4
else if (n->m_god.m_name == trav->m_god.m_name)
{
	// do nothing
}


Would this be a good idea? I have another infinite loop in main(). Is it because of this? It happens after I insert Frejya into the norse_gods list, it seems, unless I misunderstood when it's happening exactly. All I really know for sure is that it's in the first loop I have in main(). Here:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
int main()
{
	try
	{
		Link *gods = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		gods = gods->add_ordered(new Link{ { "Thor", "Norse", "Chariot pulled by goats Tanngrisnir and Tanngnjostr",
			"Hammer called Mjolnir" } });
		gods = gods->add_ordered(new Link{ { "Baldr", "Norse", "A giant ship called Hringorni", "None" } });
		gods = gods->add_ordered(new Link{ { "Frejya", "Norse", "Chariot pulled by two cats", "Magic called seidr" } });
		gods = gods->add_ordered(new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
			"Thunderbolt and the shield called Aegis" } });
		gods = gods->add_ordered(new Link{ { "Hera", "Greek", "A chariot drawn by peacocks", "Her intelligence" } });
		gods = gods->add_ordered(new Link{ { "Athena", "Greek", "", "Allowed to use Zeus's Thunderbolt and the Aegis" } });
		gods = gods->add_ordered(new Link{ { "Ares", "Greek", "War chariot", "Sword and spear" } });
		gods = gods->add_ordered(new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } });
		gods = gods->add_ordered(new Link{ { "Susanoo", "Japanese", "", "Sword of Totsuka" } });
		gods = gods->add_ordered(new Link{ { "Izanagi", "Japanese", "", "Sword of Totsuka (later given to Susanoo)" } });
		gods = gods->add_ordered(new Link{ { "Bishamonten", "Japanese", "", "A spear" } });

		Link *Odin = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		Link *Zeus = new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
			"Thunderbolt and the shield called Aegis" } };
		Link *Amaterasu = new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } };

		Link *norse_gods = Odin;
		Link *greek_gods = Zeus;
		Link *jap_gods = Amaterasu;

		Link *trav = gods->find_if_myth("Norse");
		while (trav)
		{
			if (trav == gods)
			{
				trav = gods->next();
			}
			trav->erase();
			norse_gods = norse_gods->add_ordered(trav);
		}
		trav = gods->find_if_myth("Greek");
		while (trav)
		{
			if (trav == gods)
			{
				trav = gods->next();
			}
			trav->erase();
			greek_gods = greek_gods->add_ordered(trav);
		}
		trav = gods->find_if_myth("Japanese");
		while (trav)
		{
			if (trav == gods)
			{
				trav = gods->next();
			}
			trav->erase();
			jap_gods = jap_gods->add_ordered(trav);
		}

		std::cout << "gods list:\n";
		print_all(gods);
		std::cout << "\nnorse_gods list:\n";
		print_all(norse_gods);
		std::cout << "\ngreek_gods list:\n";
		print_all(greek_gods);
		std::cout << "\njap_gods list:\n";
		print_all(jap_gods);

		delete Odin;
		delete Zeus;
		delete Amaterasu;
		delete gods;
	}
	catch (const std::runtime_error &rte)
	{
		std::cerr << "Runtime error: " << rte.what() << '\n';
		keep_window_open();
		return 1;
	}
	catch (const std::bad_alloc &ba)
	{
		std::cerr << "Bad allocation error: " << ba.what() << '\n';
		keep_window_open();
		return 2;
	}
	catch (const std::exception &e)
	{
		std::cerr << "Exception: " << e.what() << "\n";
		keep_window_open();
		return 3;
	}
	catch (...)
	{
		std::cerr << "An unknown exception occurred\n";
		keep_window_open();
		return 4;
	}

	keep_window_open();
}


Edit: How about something like this for freeing the memory?
delete &Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };

If they don't have names, I can't refer to a named pointer when using delete. This is what I have left. If this is wrong, what would you suggest?

Do I call find() on the gods list and pass in the name of the god I want to delete? Would that work? Even for the gods I've moved to another list already, since it was in the gods list that I initially allocated memory for them? But that would give me nullptr problems, right? So what should I do?
Last edited on
This is what I have left. If this is wrong, what would you suggest?

Why not just keep throwing code at the problem, that'll solve everything right? Have you done as I suggested earlier, create a project that is allocating an deleting memory using just plain old data types? You really don't seem to have a clue as to how to properly manage memory so I suggest you start simpler.

Why are you so worried about properly freeing the memory when you are still working on your "move"?

You keep saying that some of your pointers are going to nullptrs sometimes I suggest you solve these issues before you worry about deleting the memory. If you mangle the pointers and you have orphaned or nullptrs you'll never be able to properly delete the memory. You really need to work on one problem at a time, you're just confusing yourself by working on so many different projects and problems at the same time. And just throwing code at the problem is not a viable solution.



Rrandomly throwing code at the problem" is what I'm trying to avoid by bringing up that line of code and asking about it.

I'll try do the "move" thing first, then. On that note, though, I'm thinking of something along these lines for the logic:
1
2
3
4
5
6
if find_if_myth("<some_myth>") returns a valid pointer
    while pointer is valid and there is really a god from that pantheon still in the list "gods"
        if we are at the head of the list (I assume that is what trav == gods means)
            traverse list until we reach the node we want
        erase the node
        insert it into the correct list lexicographically (i.e. call add_ordered() on the node)


What do you think? For the loop condition, while (gods->find_if_myth("Norse")), for the Norse mythology list, is what I'm thinking of.
Last edited on
I tried it like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
while (gods->find_if_myth("Norse"))
{
	Link *trav = gods->find_if_myth("Norse");
	if (trav)
	{
		if (trav == gods)
		{
			trav = gods->next();
		}
	}
	trav->erase();
	norse_gods = norse_gods->add_ordered(trav);
}
while (gods->find_if_myth("Greek"))
{
	Link *trav = gods->find_if_myth("Greek");
	if (trav)
	{
		if (trav == gods)
		{
			trav = gods->next();
		}
	}
	trav->erase();
	greek_gods = greek_gods->add_ordered(trav);
}
while (gods->find_if_myth("Japanese"))
{
	Link *trav = gods->find_if_myth("Japanese");
	if (trav)
	{
		if (trav == gods)
		{
			trav = gods->next();
		}
	}
	trav->erase();
	jap_gods = jap_gods->add_ordered(trav);
}


But now I get the output:
Runtime error: Node to insert cannot be null
Please enter a character to exit


I'm checking for null, so how come it's still doing that? Is it because of erase()?

Edit: Yeah, just fixed the little "checking for null" problem (with the scope of the check being off). But the node to insert is still null.
Last edited on
I changed it to this "better and makes a little more sense" version, but the node to insert is still null:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
while (gods->find_if_myth("Norse"))
{
	Link *trav = gods->find_if_myth("Norse");
	if (trav)
	{
		if (trav == gods)
		{
			trav = gods->next();
		}
		trav->erase();
		norse_gods = norse_gods->add_ordered(trav);
	}
}
while (gods->find_if_myth("Greek"))
{
	Link *trav = gods->find_if_myth("Greek");
	if (trav)
	{
		if (trav == gods)
		{
			trav = gods->next();
		}
		trav->erase();
		if (trav)
		{
			greek_gods = greek_gods->add_ordered(trav);
		}
	}
}
while (gods->find_if_myth("Japanese"))
{
	Link *trav = gods->find_if_myth("Japanese");
	if (trav)
	{
		if (trav == gods)
		{
			trav = gods->next();
		}
		trav->erase();
		jap_gods = jap_gods->add_ordered(trav);
	}
}


I don't know why I made that silly mistake with the placement of the
1
2
trav->erase();
jap_gods = jap_gods->add_ordered(trav);
lines earlier.

Edit: And for some reason, it's also inserting nodes into the wrong lists. I saw it put Hera and also all of the Japanese gods into the Norse gods list. Did I make a mistake in my find_if_myth() function? Or am I doing something incorrectly in main()?
Last edited on
Pages: 1... 1011121314... 16