so I have a struct bullet:
struct Bullet {
int posX; int posY;
int verticalBulLimiter = 0;
int verticalBulLimiterCheck = 35; // aka movement Speed
void draw() {
gotoxy(posX,posY);
setColor(14);
cout << bullet << endl;
if (posY - 1 == 0){
/// I want to delete struct here
}
if (verticalBulLimiter == verticalBulLimiterCheck) {
posY--;
clearPixel(posX, posY + 1);
verticalBulLimiter = 0;
}
else {
verticalBulLimiter++;
}
}
};
as You can see I want to delete the struct once it's variable posY reaches certain value.
So how do I do that. Do I tried using keyword "this" but I dont really know how does it work. Is there any function for 'self destruction' ?
While this can be possible using delete this, it is most definitely not what you want.
Objects in C++ do not usually own themselves, so you should have the owner of the bullet (maybe a scene or world entity) delete it.
Instead of trying to "destroy a struct from within", you should be checking and removing instances of struct that have met some conditions.
There's an algorithm that does just that, like so.
#include <vector>
struct Bullet { ... };
std::vector<Bullet> bullets;
void clean_bullets(){
bullets.erase(
std::remove_if(bullets.begin(), bullets.end(),
[](const Bullet& i){return /* your condition when a bullet should be removed */}),
v.end()
);
}
int main(){
// Add some bullets
bulltes.push_back({/* create a bullet here */});
.
.
.
clean_bullets();
}
The std::vector<Bullet> bullets contains all the bullets, and is responsible for memory, removing, adding elements etc.
You can read more about std::vector here: https://en.cppreference.com/w/cpp/container/vector
And about removing the elements like above, it's called the remove/erase idiom https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove
Related
I have a list of Slide objects. Each Slide object has a vector of slide elements, the slide element vector is of another class,say ItemProperties that has members
int Resize
int Rotate
int Move
and the functions to modify these values
void ResizeItem(int resize_val);
void RotateItem(int rotate_val);
void MoveItem(int move_val);
I am iterating the list of object like this
"Iterating Part"
auto slidelist_ptr=VDECK.getSlideList(); /*returns list<Slide> by reference */
auto slidelist_itr=slidelist_ptr.begin(); /*returns iterator to beginning of Slide list*/
auto slidelemnts_itr=slidelist_itr->getSlideElemnt().begin(); /*returns iterator to beginning of slide list elements*/
in1=_getch();
if(in1!=KEY_ARROW_1)
{
**VDECK.selectedSlideOperations((*slidelist_itr),in1-48);**
throw std::runtime_error("Operation success\n");
}
++slidelist_itr;
slidelemnts_itr=slidelist_itr->getSlideElemnt().begin();
In the function selectedSlideOperations , I am passing the particular slide object and taking it as reference in function like this
void Deck::selectedSlideOperations(Slide &obj,int choice)
{
switch(choice)
{
case 5:
ChangeSlideItemProperties(obj);
break;
}
}
In ChangeSlideItemProperties , I am again taking the object as reference
void Deck::ChangeSlideItemProperties(Slide &obj)
{
for(auto p=obj.getSlideElemnt().begin();p!=obj.getSlideElemnt().end();p++)
{
std::cout<<"before \n";
p->PrintItemProperties();
p->RotateItem(input);
std::cout<<"\nafter \n";
p->PrintItemProperties();
}
}
Inside this I am iterating the Slide object's slide elements(which is a vector) and trying to modify the value of member "Rotate" for all the elements in vector.
After modification when I print "before" and "after" the members ,the value reflects properly for member Rotate.
However after modification ,when I exit this menu and print the slide elements using iteration as shown in "Iterating part" , the values are 0's for all the members.
I am fairly new to C++ , please bear with me.... I am not sure what am I missing here.
Edit: Sorry I changed the slide elements to list instead of vector , so I have lists only and no vectors
Edit 2: Adding minimal reproducible example
using namespace std;
class Itemprop
{
int Rotate;
public:
Itemprop():Rotate{0}{}
void Set_Rotate(int val)
{
Rotate = val;
}
int Get_Rotate()const
{
return Rotate;
}
};
class Dummy
{
public:
Dummy();
list<Itemprop>& getList(void)
{
return v;
}
virtual ~Dummy();
protected:
private:
list<Itemprop> v;
};
int main()
{
Dummy dobj;
Itemprop iobj;
iobj.Set_Rotate(1);
dobj.getList().emplace_back(iobj);
Itemprop iobj2;
iobj2.Set_Rotate(2);
dobj.getList().emplace_back(iobj2);
for(auto p:dobj.getList())
{
cout<<"before\n";
cout<<p.Get_Rotate()<<endl;
p.Set_Rotate(3);
cout<<"after\n";
cout<<p.Get_Rotate()<<endl;
}
for(auto p:dobj.getList())
{
cout<<p.Get_Rotate()<<"<--new\n";
}
Output is
before
1
after
3
before
2
after
3
1<--new
2<--new
Because your range loop that uses auto keyword is taking the elements of your list (the list itself is taken by reference) by copy.
Quick fix is to take the elements by reference as well, e.g.:
for(auto& p:dobj.getList())
Or you can use the std::list iterators, like in the previous code you posted:
for(auto it = dobj.getList().begin(); it != dobj.getList().end(); it++)
{
cout<<"before\n";
cout<<it->Get_Rotate()<<endl;
it->Set_Rotate(3);
cout<<"after\n";
cout<<it->Get_Rotate()<<endl;
}
I have two classes, in the example added Rectangle and Rectangles. The goal is to make one Rectangles object which holds references to multiple Rectangle objects.
If I change r by r.set_values(4,4) then off coarse r.area() is changed. However if I call rectangles.rects[0].area() it remains 12, and therefore is not changed.
As I understood I am making a reference of r in rectangles, however this seems to be wrong.
How to achieve this?
The code is available here
#include <iostream>
using namespace std;
class Rectangle {
int width, height;
public:
void set_values (int,int);
int area() {return width*height;}
};
void Rectangle::set_values (int x, int y) {
width = x;
height = y;
}
class Rectangles {
public:
Rectangles(int n);
void addRectangle(Rectangle* r);
Rectangle* rects;
int nRects;
};
Rectangles::Rectangles(int n) {
rects = new Rectangle[n];
nRects = 0;
}
void Rectangles::addRectangle(Rectangle* r) {
rects[nRects] = *r;
nRects++;
}
int main() {
Rectangle r;
Rectangles rectangles(5);
r.set_values(4,3);
rectangles.addRectangle(&r);
cout<<"r.area() before change:"<<r.area()<<endl;
cout<<"rectangles.rects[0].area() before change:"<<rectangles.rects[0].area()<<endl;
r.set_values(4,4);
cout<<"r.area() after change:"<<r.area()<<endl;
cout<<"rectangles.rects[0].area() after change:"<<rectangles.rects[0].area()<<endl;
return 0;
}
Output:
r.area() before change:12
rectangles.rects[0].area() before change:12
r.area() after change:16
rectangles.rects[0].area() after change:12
What is wrong with your code is your definition of Rectangles. It stores a pointer (or an array) to a Rectangle. What you want here is not an array of Rectangle's, but an array of references to Rectangle's. Here, the references shall be pointers, so you need to change this accordingly :
class Rectangles {
public:
Rectangles(int n);
void addRectangle(Rectangle* r);
// Rectangle* rects;
// What you really want :
Rectangle** rects;
int nRects;
};
But then you also need to change the implementation :
Rectangles::Rectangles(int n) {
rects = new Rectangle*[n]; // Array of pointers
nRects = 0;
}
void Rectangles::addRectangle(Rectangle* r) {
rects[nRects] = r; // r is a pointer : just store it, no dereferencing
nRects++;
}
However, this is a bad design : you should not have to use any of these : pointer to pointer (or 'raw array' of pointers), new, and a class whose only purpose is to store an array of things. This is because you already have better tools for this : smart pointers (although you do not need them here either), arrays and dynamic arrays (or vectors).
So, if I were you, this is how I would rewrite your code :
#include <iostream>
#include <vector>
class Rectangle {
public:
void setSize(int w, int h);
int area();
private:
int width, height;
};
void Rectangle::setSize(int w, int h) {
width = w;
height = h;
}
int Rectangle::area() {
return width * height;
}
int main() {
Rectangle r;
std::vector<Rectangle*> rectangles;
r.setSize(4, 3);
rectangles.push_back(&r);
std::cout << "r.area() before change : " << r.area() << std::endl
<< "rectangles[0]->area() before change : "
<< rectangles[0]->area() << std::endl;
r.setSize(4, 4);
std::cout << "r.area() after change : " << r.area() << std::endl
<< "rectangles.rects[0]->area() after change : "
<< rectangles[0]->area() << std::endl;
return 0;
}
Edit :
You might wonder why I used a raw pointer instead of a smart pointer (since I told you to avoid pointers to pointer). This is quite simple : no smart pointer would fit the matter. Let us see why.
std::unique_ptr keeps sole ownership of the object. What if you want another reference to it ? Also, if you ever destroy this smart pointer via std::vector's erase, it would also destroy your object. So if you access it afterwards, you would get some dirty error.
std::shared_ptr keeps shared ownership of the object. Sure, you can have another reference to your object, but the same thing happens if you destroy the pointer. Also, it has some overhead, and is not so easy to use correctly.
std::weak_ptr works with std::shared_ptr, nothing more to say.
A raw pointer, on the contrary, only needs you to ensure that the lifetime of the object is longer or equal to its own lifetime, so that you can always access your object via the pointer. And that is all.
Finally, here is a general rule of thumbs (that I use) :
unique_ptrs are for sole ownership
raw pointers mean whoever gave me the raw pointer guarantees the lifetime of that object to match or exceed my lifetime.
shared_ptrs are for shared ownership
weak_ptrs are for when a system wants to check if the object still exists before using it. This is rare in my code since I find it cleaner to have a system guarantee the lifetime of anything it passes it's subsystems (in which case I use a raw pointer)
class Rectangles {
public:
void addRectangle(Rectangle* r);
vector<Rectangle *> rects;
};
void Rectangles::addRectangle(Rectangle* r) {
rects.push_back(r);
}
int main() {
Rectangle r;
Rectangles rectangles;
r.set_values(4,3);
rectangles.addRectangle(&r);
cout<<"r.area() before change:"<<r.area()<<endl;
cout<<"rectangles.rects[0]->area() before change:"<<rectangles.rects[0]->area()<<endl;
r.set_values(4,4);
cout<<"r.area() after change:"<<r.area()<<endl;
cout<<"rectangles.rects[0]->area() after change:"<<rectangles.rects[0]->area()<<endl;
return 0;
}
Output:
r.area() before change:12
rectangles.rects[0]->area() before change:12
r.area() after change:16
rectangles.rects[0]->area() after change:16
A while ago I asked a question on why the following code did not work:
std::vector<std::vector<std::vector<Tile_Base*>>> map_tile; // This is located in Map object. See below.
int t_x, t_y;
t_x = t_y = 200;
map_tiles.begin(); // clear(), resize() and every other function still causes problems
The thing is, is that it should have worked, yet Visual Studios 2012 throws an exception when the resize function is called. The exception pointed to this piece of code:
*_Pnext != 0; *_Pnext = (*_Pnext)->_Mynextiter)
located in xutility. It said that there was an violating on access to reading the memory. I thought maybe somehow I lost access to the member along the way? (Using VS' watch I saw the memory was not corrupted)
So, I fiddled around with the code and tried to figure out what could possibly be going wrong, and after awhile I moved the map_tiles object down to the bottom of the list, and it worked:
// WORKS
class Map {
std::vector<Tile_Base*> spawn_tiles;
// map tile specific
bool Is_Valid(int,int);
std::string name;
std::vector<std::vector<std::vector<Tile_Base*> > > map_tiles;
public:
// ...
}
// DOESN'T WORK
class Map {
std::vector<std::vector<std::vector<Tile_Base*> > > map_tiles;
std::vector<Tile_Base*> spawn_tiles;
// map tile specific
bool Is_Valid(int,int);
std::string name;
public:
// ...
}
Any help pointing out what went wrong? I can't come up with any reasonable explanation.
A vector<T> comprises two discrete sets of data: the internal state and the array of Ts. The internal state - capacity, size, pointer - is separate from the array. The issue you're describing is normally caused by something overwriting the vector object, i.e the internal state. To track this down easily you could use a container class:
typedef std::vector<std::vector<std::vector<Tile_Base*> > > maptiles_t;
class CMapTiles
{
unsigned int m_guard;
maptiles_t m_tiles;
enum { Guard = 0xdeadbeef };
public:
CMapTiles() : m_guard(Guard), m_tiles() {}
~CMapTiles() { assert(m_guard == Guard); }
void Check()
{
#if defined(DEBUG)
if (m_guard != Guard)
DebugBreak();
#endif
}
void Resize(size_t x, size_t y)
{
Check();
auto init = std::vector<std::vector<Tile_Base*> >(y/32);
m_tiles.resize(m_x / 32, init);
Check();
}
const maptiles_t& tiles() const { Check(); return m_tiles; }
maptiles_t& tiles() { Check(); return m_tiles; }
};
And instead of using std::vector<...> map_tiles have CMapTiles map_tiles, and then when you want to get at the vector, map_tiles.tiles().
Hope this helps.
I have a struct Creature and a struct Game. Game is a "friend" of Creature.
In game I have
vector creatures;
and I add a creature x to that vector thourgh a function called addC
void addc (Creature& c){
creatures.push_back(c);
}
Now I'm in another function "foo" that is a public method of the struct Game.
void foo (Creature& c){
...
}
In that function I need to find another creature from the vector creatures that
matches some information from Creature c.
So I made another public method in Game called fooHelper
void fooHelper (char s, int x, int y){
bool found = false;
for (int i = 0; i < creatures.size() && (!found); ++i){
Creature& c = creatures[i];
if (x == c.x && y == c.y){
c.s = s;
found = true;
}
}
}
however when I check if the second creature's "s" member is being updated, it turns out that
it is not! I don't understand what I'm doing wrong since I'm pushing by references to the vector.
and I'm getting the creature by reference from the vector.
the vector in game looks like this
struct Game{
private:
vector<Creature> creatures;
...
}
struct Creature{
private:
char s;
int x; int y;
...
}
any help would be much appreciated!
This statement:
creatures.push_back(c);
Stores a copy of c into your vector: standard containers have value semantics. If you need reference semantics, you should store pointers into your vector.
Usually it is a good idea to use smart pointers, and which one to use depends on the ownership policy of your application. In this case, based on the information I could get from your question's text, it seems reasonable to let Game be the unique owner of all Creatures in the game (and therefore the only object which is responsible for the lifetime of the owned Creatures, and in particular for destroying them when they won't be needed anymore), so std::unique_ptr should be a good choice:
#include <memory> // For std::unique_ptr
struct Game{
private:
std::vector<std::unique_ptr<Creature>> creatures;
...
};
Your member function addc() would then become:
void addc(std::unique_ptr<Creature> c)
{
creatures.push_back(std::move(c));
}
And a client would invoke it this way:
Game g;
// ...
std::unique_ptr<Creature> c(new Creature());
g.addc(std::move(c));
Your foohelper() function, on the other hand, would be rewritten into something like this:
void fooHelper (char s, int x, int y) {
bool found = false;
for (int i = 0; i < creatures.size() && (!found); ++i){
std::unique_ptr<Creature>& c = creatures[i];
if (x == c->x && y == c->y) {
c->s = s;
found = true;
}
}
}
Finally, your class Game could return non-owning raw pointers (or references) to clients requiring access to the stored creatures.
When you push your creature reference into the vector, it's making a copy. It's a vector of type "Creature", and so it's making a copy from the reference that you give it. One solution would be to keep a vector of creature pointers.
edit - this question helps explain things a little better than I was able to on why you can't have a vector of references: Why can't I make a vector of references?
I have a relatively simple question but I cant seem to find an answer specific for my case and I just may not be approaching this problem the right way. I have a class that looks like this:
struct tileProperties
{
int x;
int y;
};
class LoadMap
{
private:
ALLEGRO_BITMAP *mapToLoad[10][10];
tileProperties *individualMapTile[100];
public:
//Get the struct of tile properties
tileProperties *getMapTiles();
};
I have an implementation that looks like this for the getter function:
tileProperties *LoadMap::getMapTiles()
{
return individualMapTile[0];
}
I have code in the LoadMap class that will assign 100 tile properties for each struct in the array. I want to be able to access this array of structs in my main.cpp file but I just cant seem to find the right syntax or approach. My main.cpp looks like this.
struct TestStruct
{
int x;
int y;
};
int main()
{
LoadMap _loadMap;
TestStruct *_testStruct[100];
//This assignment will not work, is there
//a better way?
_testStruct = _loadMap.getMapTiles();
return 0;
}
I realize that there are many approaches to this, but I'm trying to keep this implementation as private as possible. If someone could please point me in the right direction I would greatly appreciate it. Thank you!
TestStruct *_testStruct;
_testStruct = _loadMap.getMapTiles();
This will get you a pointer to the first element in the array returned. You can then iterate through the other 99.
I would highly recommend using vectors, or another container, and writing getters that don't return pointers to bare arrays like that.
First of all, here, why do we need TestStruct, you can use "tileProperties" structure itself...
And imp thing,
tileProperties *individualMapTile[100]; is array of pointers to the structure.
Hence, individualMapTile will have pointers in it.
You have returned the first pointer, hence you can access the first structure only. What about the others????
tileProperties** LoadMap::getMapTiles()
{
return individualMapTile;
}
int main()
{
LoadMap _loadMap;
tileProperties **_tileProperties;
_tileProperties = _loadMap.getMapTiles();
for (int i=0; i<100;i++)
{
printf("\n%d", (**_tileProperties).x);
_tileProperties;
}
return 0;
}
Use vectors instead of arrays where possible. Also consider an array/vector of TestStruct directly rather than pointers to them. I can't tell if that would be appropriate for you from your code sample.
class LoadMap
{
public:
typedef vector<tileProperties *> MapTileContainer;
LoadMap()
: individualMapTile(100) // size 100
{
// populate vector..
}
//Get the struct of tile properties
const MapTileContainer& getMapTiles() const
{
return individualMapTile;
}
MapTileContainer& getMapTiles()
{
return individualMapTile;
}
private:
MapTileContainer individualMapTile;
};
int main()
{
LoadMap _loadMap;
LoadMap::MapTileContainer& _testStruct = _loadMap.getMapTiles();
}