Remove item from C-array and shift

Pages: 12
If you really want to do this using pointers, consider:

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
#include <iostream>
#include <string>

class Monster {
public:
	Monster() {};
	Monster(const std::string& name) : name(name) {}

	std::string getName() const { return name; }

private:
	std::string name;
};

class Monsters {
public:
	auto begin() const noexcept { return monsters; }
	auto end() const noexcept { return monsters + total; }

	Monsters(size_t max) :max(max), monsters(new Monster*[max]) {}

	~Monsters()
	{
		for (auto& m : *this)
			delete m;

		delete[] monsters;
	}

	bool add(const Monster* m) noexcept
	{
		if (total < max) {
			monsters[total++] = const_cast<Monster*>(m);
			return true;
		}

		return false;
	}

	bool remove(const Monster* m) noexcept
	{
		for (auto& mptr : *this)
			if (mptr == m) {
				mptr = monsters[--total];
				delete m;
				return true;
			}

		return false;
	}

private:
	Monster** monsters {nullptr};
	size_t max {0};
	size_t total {0};
};

std::ostream& operator<<(std::ostream& os, const Monsters& mon)
{
	for (const auto& m : mon)
		os << m->getName() << std::endl;

	return os;
}

int main()
{
	constexpr size_t size = 5;

	try {
		Monsters monsters(size);

		const auto monster1 = new Monster("Sally");
		const auto monster2 = new Monster("Rich");

		std::cout << "Added " << (monsters.add(monster1) ? "OK" : "failed") << std::endl;
		std::cout << "Added " << (monsters.add(monster2) ? "OK" : "failed") << std::endl;
		std::cout << monsters << std::endl;

		std::cout << "Removed " << (monsters.remove(monster1) ? "OK" : "failed") << std::endl;
		std::cout << monsters << std::endl;

		std::cout << "Added " << (monsters.add(new Monster("Monster")) ? "OK" : "failed") << std::endl;
		std::cout << monsters << std::endl;
	}
	catch (...) {
		std::cout << "Error!\n";
	}
}


displaying:


Added OK
Added OK
Sally
Rich

Removed OK
Rich

Added OK
Rich
Monster

Can't the index of a pointer be used?
It can, but why would you want to? The optimizer will almost certainly make equivalent code and the index notation is much clearer, at least to me.
I have a question about your remove function.

Why are you deleting "m", the parameter? The function doesn't own the memory for m, so it can be dangerous to delete that memory.

Do you know that you can pass a statically allocated monster pointer to this function? What happens when you try to delete a variable that has not been allocated with new?

1
2
3
Monster monster3{"Bad Boy"};
monsters.add(&monster3);
monsters.remove(&monster3);


The above should compile, but should also cause problems with your code.

Yes - I know. The code was only an example of how it might be done - not best practice. main() used new to allocate the memory and you could do:

 
monsters.add(new Monster ("monster"));


In this case if you don't delete m you have a memory leak.

This is why previous posts have stated not to use pointers!

I don't like this code - it's way too flakey! Arrays of raw pointers are an accident waiting to happen IMO.

main() used new to allocate the memory

Which is, IMO, probably one of the poorest practices in the whole program.

I agree about the flakey, especially since it is possible to do the program without the pointers (raw or smart), even if you "must" use a dynamic array in the Monsters class.

I agree that using new to allocate memory in main() is poor. That was how @alix did it in post #1 so I just followed through. For anyone reading these posts, this is not how you do it.
Topic archived. No new replies allowed.
Pages: 12