I am dealing with a task to create a troop of bunnies where they can multiply at each round. So I define a class of Bunny (individual), and then define a class of Troop with a vector point to different bunnies.
My problem is, every time I use new to create an object Bunny in a loop, it will come out an error says:
"Debug assertion failed!!...vector iterator not incrementable..."
Here is a sample of my code:
class Bunny {
private:
string sex;
string color;
string name;
int age;
public:
string getname() { return name;};
Bunny(); // constructor
};
class Troop {
private:
vector<Bunny *> bunpointer;
vector<Bunny *>::iterator it;
public:
void newbunny();
void multiply();
};
void Troop::newbunny() {
Bunny * bun; // pointer to the Bunny class
bun = new Bunny;
cout << "Bunny " << bun->getname() << " is born! \n";
bunpointer.push_back(bun);
}
void Troop::multiply() {
it = bunpointer.begin();
while(it!=bunpointer.end()) {
cout << (*it)->getname() << " gave a birth. ";
newbunny();
++it;
}
it = bunpointer.begin();
}
So if I create 5 bunnies at the beginning, and call function Troop::multiply, there should be 10 bunnies. An interesting observation is, the error will occur after 2 bunnies being born.
I think the problem may lie in the use of new to create new objects in a iterator loop. The new may somehow interrupt the iterator pointer *it. But I am not sure if this is the case, and if it really is, how to deal with this.
modified: so it is actually a problem of using push_back(), which will probably invalidate the iterator!!
Thank you in advance!!
1) Unless you have a reason to, your code does not need to use new at all. The code becomes easier, and no chance of memory leaks. Also, I don't see the need for an iterator member in the Troop class, unless you can justify the reason for it.
2) As to your immediate problem, just use a non-iterator reliant loop. In other words, a simple loop that goes from 0 to the number of current bunnies, less 1.
Here is an example:
#include <vector>
//...
class Troop {
private:
std::vector<Bunny> bunpointer;
public:
void newbunny();
void multiply();
};
void Troop::newbunny() {
bunpointer.push_back(Bunny());
}
void Troop::multiply() {
size_t siz = bunpoiner.size();
for (size_t i = 0; i < siz; ++i ) {
newbunny();
cout << (*it)->getname() << " gave a birth. ";
}
}
The newbunny() function simply creates a Bunny() using a default constructor and adds the item to the vector.
If you want to use a container that doesn't invalidate iterators when inserting items, then you can use a std::list as opposed to a std::vector.
It appears that you are trying to modify the std::vector while iterating over it. This is generally not a good idea, for a variety of reasons.
In particular, when you call newbunny() inside the iterator's loop, it is possible that the iterator you used to hold will be invalidated, because the vector may be resized during the push_back.
See this question for details.
As mentioned by others, the push_back() is your culprit, not the new.
One way to palliate would be this:
size_t const max(bunpointer.size());
for(size_t i(0); i < max; ++i)
{
cout << bunpointer[i]->getname() << " gave a birth. ";
newbunny();
}
This works because you are only adding new bunnies at the end of your existing vector. These new bunnies are not taken in account by the loop (max doesn't change because you call newbunny()...) and the [i] access makes use of the vector in its current state.
That loop would not work if you were deleting items...
As a side note: the name "bunpointer" is not very clear... it's not a pointer, it's a vector of pointers.
Related
I have a playlist class which contains a vector of song pointers.
class Playlist {
public:
Playlist();
Playlist(string);
vector<Song*> GetSongList() const;
private:
vector<Song*> songs;
string name;
};
The function GetSongList() is as follows:
vector<Song*> Playlist::GetSongList() const {
return songs;
}
In my main method I have a vector of playlist pointers: vector<Playlist*> playlists
I want to remove a song pointer from a specific playlist, but I'm having trouble. This is my current code to remove the indicated song:
Playlist* desiredPlaylist = playlists.at(index);
vector<Song*> temporarySongList = desiredPlaylist->GetSongList();
cout << "Pick a song index number to delete: ";
cin >> index;
temporarySongList.erase(tempSongList.begin() + index);
When I erase the song from the vector and re-output the contents of playlists.at(index).GetSongList() the song is not removed. I think the reason why is that calling GetSongList() does not retrieve the actual song vector, but just returns a copy, so I'm not altering the original vector. How do I directly remove the song from the original?
Use a member function remove_playlist to remove the song from the playlist. std::list (in place of vector) is recommended since frequent delete, move and insert is required within the playlist. Also use smart-pointer to avoid memory leaks like this std::list<std::shared_ptr<Song>>
void Playlist::remove_playlist(int index)
{
if( index < songs.size() )
{
auto v = songs.at(index);
songs.erase(std::remove(songs.begin(), songs.end(), v), songs.end());
}
}
You are right, the problem is caused by returning a copy.
You can either return a pointer
vector<Song*>* Playlist::GetSongList() {
return &songs;
}
or a reference
vector<Song*>& Playlist::GetSongList() {
return songs;
}
to your playlist.
A pointer is preferrable when it may happen, that there is no song list available and you thus sometimes have to return nullptr. So not in your example, because the member playlist is always available.
In most other cases, returning a reference is preferrable. Note that the method is not marked as const, because accesses to the returned vector<Song*>& alter the Playlist instance.
Another technique is to not return the member at all, but instead use a delegate to change the member.
void Playlist::ChangeSongList( const std::function<void(vector<Song*>&)>& fn ) {
fn(songs);
}
This has the benefit that the class which supplies the member can lock the access to the member in a threaded environment and is better informed when the member is changed (e.g. for debugging purposes - ChangeSongList could dump the contents before and after calling fn())
Anyway, returning a copy has often also performance problems and thus is often not preferrable. If you want to return a const member, you should use a const reference instead:
const vector<Song*>& Playlist::GetSongList() const {
return songs;
}
Please note that the answer seccpur gave is the most preferrable option in everyday life - a class should and usually takes care of its members itself, and don't let some outside code handle it. But this answer doesn't describe the difference in returning copies, pointers and references.
Quote
Playlist* desiredPlaylist = playlists.at(index);
vector<Song*> temporarySongList = desiredPlaylist->GetSongList();
cout << "Pick a song index number to delete: ";
cin >> index;
temporarySongList.erase(tempSongList.begin() + index);
You are creating a copy by doing this
vector<Song*> temporarySongList = desiredPlaylist->GetSongList();
So you are erasing from your local copy.
Consider changing
vector<Song*> GetSongList() const { return songs };
to
vector<Song*>& GetSongList() { return songs } ;
I am trying to write a program that will solve a maze using a class and a tree. I am trying to use a class to represent the maze (the design will be entered using cin), and the class contains a struct as a private member.
This struct contains two ints (for the x and y coordinate of the position) and an array with 3 spaces that will hold three pointers to other structs.
In the constructor function for my class, I am trying to set all the pointers in the array to NULL to start off. The program compiles fine, but when I get to the constructor the program gives me a segmentation fault. Here is some relevant code:
const int POSSIBLE_BRANCHES = 3; //at any point the path can split in 3 ways
struct PathNode
{
int x_coord;
int y_coord;
PathList branches[POSSIBLE_BRANCHES];
};
typedef PathNode *PathList;
class Maze
{
private:
PathList initial_pos;
public:
Maze();
};
And the constructor:
Maze::Maze()
{
cout << "entered constructor" << endl;
for (int i = 0; i < POSSIBLE_BRANCHES; i++)
{
initial_pos->branches[i] = NULL;
}
}
I get the "entered constructor" phrase printed out, but the program stops immediately afterwards. I am assuming it is some silly problem with my pointer syntax, but I have been unable to locate the problem.
As I understand it: the -> operator dereferences the pointer to the PathNode struct, so now we have access to the members like x_coord, y_coord, and branches. The [] operator gets to each index of the branches array. And because it is an array of pointers to PathNodes, setting them as NULL should be fine. Where is the flaw in my reasoning?
Edit:
Solved. See the answer marked as best.
You haven't yet allocated initial_pos before you use it. That is causing the segfault.
Something along the lines of:
Maze::Maze()
: initial_pos(new PathNode)
{
cout << "entered constructor" << endl;
for (int i = 0; i < POSSIBLE_BRANCHES; i++)
{
initial_pos->branches[i] = NULL;
}
}
Should fix your problem.
Your constructor is the first thing that gets called for the new class, so you never allocate or initialize initial_pos in anyway, but you then dereference it - leading to undefined behavior (most likely causing a segfault)
I store the data in a double std::vector structure, which I need to be able to fill and clear repeatedly: this is causing some allocation issues I don't understand.
I am using a structure vector<Coefficients *> XSims, where Coefficients takes the form
class Coefficients{
int N;
public:
vector<gsl_vector *> Coefs;
//Iterator to traverse the vector structure.
vector<gsl_vector*>::iterator it;
void it_start(){
it = Coefs.begin();
}
void it_end(){
it = Coefs.end();
}
void it_next(){
++it;
}
void it_prev(){
--it;
}
bool not_end(){
return it < Coefs.end();
}
//Return number of vectors contained.
size_t length(){return Coefs.size();}
//Append pointer to outside data into the Coefs structure.
void append( gsl_vector * X ){
Coefs.push_back(X);
}
Coefficients(int N1) : N(N1) {
Coefs.reserve(N);
}
//Clean up procedure
void Clear(){
//Forward iterator.
it_start();
while(not_end()){
gsl_vector_free((*it));
it_next();
}
Coefs.clear();
}
~Coefficients(){
//Forward iterator.
Clear();
Coefficients::Coefs.clear();
}
};
I use the following iterator to get around XSim:
vector<Coefficients *>::iterator Xit;
inline void Xstart(){Xit = XSims.begin();}
inline void Xend(){Xit = XSims.end();}
inline void X_next(){++Xit;}
inline void X_previous(){--Xit;}
inline bool X_not_end(){return {Xit < XSims.end()};}
The two functions I'm struggling to use in combination are as follows:
inline void Simulate(){
XSims.reserve(N+1);
Xstart();
for(int i=0;i<N; i++){
//Build a container to insert into XSims
Coefficients * XsimsIteration = new Coefficients(1000);
// time points to previous vector of simulations.
(*Xit)->it_start();
for(int m=0;m<1000;m++){
//Allocate free space for the components of the DW and Xsims.
gsl_vector * X = gsl_vector_alloc(X0.X0->size);
XsimsIteration->append(X);
gsl_vector_memcpy(X,(*Xit));
//Next simulation
(*Xit)->it_next();
}
cout << "Number of sims being inserted into X = " << XsimsIteration->length() << endl;
//Insert XsimsIteration into the XSims container
XSims.push_back(XsimsIteration);
//next time point
X_next();
cout << "Number of simulations stored in X = " << (*Xit)->length() << endl;
}
}
inline void XW_clear(){
Xstart();
//Don't want to clear the initial values, so step forward!
X_next();
while(X_not_end()){
(*Xit)->Clear();
X_next();
}
XSims.clear();
}
I want to run the two functions in loop: After initializing the XSims with an initial Coeffiecient* (which never gets cleared), I run
Simulate();
XW_clear();
Simulate();
The first two functions work fine, but the second Simulate() crashes in run-time. Basically, it seems not to want to push_back the XsimsIteration on the second outer-loop: I get the strange output:
Number of sims being inserted into X = 1000
Number of simulations stored in X = 0
The second Number of simulations stored in X should in fact be the same as the first, i.e. 1000.
Your test for the end is not correct
inline bool X_not_end(){return {Xit < XSims.end()};}
This kind of test will work, if you have plain C/C++ arrays, but it need not work with containers. The test should be Xit != XSims.end(), not <, so it should read
inline bool X_not_end(){return Xit != XSims.end();}
Same goes for Coefficients::not_end().
Taking a look at this:
inline void Simulate(){
XSims.reserve(N+1);
Xstart();
for(int i=0;i<N; i++){
//Build a container to insert into XSims
Coefficients * XsimsIteration = new Coefficients(1000);
// time points to previous vector of simulations.
(*Xit)->it_start();
I see that you have reserved some memory for XSims. Then you call XStart() which executes XSims.begin(). You are calling a member function begin on a vector with zero elements. That seems like a red flag to me right there. Since you posted your code on a public domain, I can't help but critique it. It seems like you are obfuscating some very simple operations such as incrementing a decrementing an interator. The calls to begin, end, and moving forward and backward are already very simple. All that you have done is to make your program difficult to read.
Then you will use that iterator which is not valid to call a function on a nonexisting Coeffecients object. Only after the for loop which comes later do you actually put something into the vector.
The following lines of code are being executed before you put any elements into the XSims vector.
(*Xit)->it_start();
(*Xit)->it_next(); // why is this in the for loop? You are iterating over an empty vector
For future reference, I highly recommend that you post a compilable example. You will typically learn a lot during the process, and often one will find their own problem while doing so and debugging. In this case one has to assume many things about what you might or might not be doing in the actual executable program.
It worked if I cleared the XSims from the back rather than from the front, I guess it was throwing out everything including the initial value that I wanted to keep.
I have a vector of object pointers
std::vector<Element*> elements;
When iterating through the vector, I would like to double dereference the iterator in order to call the object's methods.
std::cout << (*it)->getName() << std::endl;
This leads to a segfault. The relevant code is below.
I am thinking that the problem is with how I am initializing the vector, because I could move the for-loop to be in the method initialize() and it works fine. In takeTurn(), the vector is of the appropriate size and the pointers contain the correct addresses. Does this mean that the objects being pointed to are being prematurely destroyed?
main.cpp:
#include <vector>
#include <iostream>
#include "Element.h"
std::vector<Element*> elements;
void initialize() {
Element ice = Element("ice",1);
Element fire = Element("fire",2);
elements.push_back(&ice);
elements.push_back(&fire);
}
void takeTurn() {
std::vector<Element*>::iterator it;
for(it = elements.begin(); it != elements.end(); ++it) {
std::cout << (*it)->getName() << std::endl;
}
}
int main() {
initialize();
takeTurn();
return 0;
}
Element.h:
#include <string>
class Element {
public:
Element(std::string name, int id);
int getID() { return id_; }
std::string getName() { return name_; }
private:
int id_;
std::string name_;
};
Element.cpp:
#include "Element.h"
Element::Element(std::string name, int id) {
name_ = name;
id_ = id;
}
Your initialize function is broken. You create local objects, and then push their addresses onto the vector. But when the function returns, those objects are destroyed, and the pointers are no longer valid. The simplest fix, unless you need polymorphism, is to just make a vector of Element objects, instead of pointers.
std::vector<Element> elements;
...
elements.push_back(Element("ice",1));
elements.push_back(Element("fire",2));
If you need polymorphism, then use smart pointers.
std::vector<std::unique_ptr<Element>> elements;
...
elements.push_back(std::unique_ptr<Element>(new Element("ice",1)));
elements.push_back(std::unique_ptr<Element>(new Element("fire",2)));
If you were to continue to use raw pointers, then you would need some way to ensure the persistence of the objects, perhaps by allocating them with new. You would then need to ensure you call delete on each of those pointers you are done with them. I do not recommend this route.
You are passing pointers to local variables to the vector here:
Element ice = Element("ice",1);
Element fire = Element("fire",2);
elements.push_back(&ice);
elements.push_back(&fire);
When you exit the function, ice, and fire cease to exist, so you are left with dangling pointers.
The solution to this problem depends on whether you really need a vector of pointers. It might be simpler to have std::vector<Element>:
std::vector<Element> elements;
then
elements.push_back(Element("ice",1));
elements.push_back(Element("fire",2));
You push dangling pointers into your vector:
void initialize() {
Element ice = Element("ice",1);
Element fire = Element("fire",2);
elements.push_back(&ice);
elements.push_back(&fire);
}
here ice and fire is local variable. You push the address to the vector, then as final } is reached both get destroyed. Later when you rereference this invalid pointer behavior is undefined.
Your vector is storing pointers to local variables that are created on the stack. When the function is finished, the memory occupied by these variables will be reclaimed. If you try to access the memory, you will get a segfault.
void initialize() {
Element ice = Element("ice",1); // Local variable.
Element fire = Element("fire",2); // Local variable.
elements.push_back(&ice);
elements.push_back(&fire);
} // Ice and fire disappear.
Allocate the memory for the elements on the heap:
void initialize() {
Element *ice = new Element("ice",1);
Element *fire = new Element("fire",2);
elements.push_back(ice);
elements.push_back(fire);
}
Remember to free the memory when you are finished!
typedef std::vector<Element *>::iterator EIter;
for (EIter it = elements.begin(); it != elements.end(); ++it) {
delete *it;
}
I am looking to be pointed in the right direction.
I have 1 class Event
class Event{
private:
vector<string> Question;
char Mode;// 1 = Ascending 2 = Descending 3 = None
string EventName;
public:
Event(string Name){
EventName = Name;
SetQuestionSize();
SetQuestion();
Mode = 3;
}
void SetName(string NewName){
EventName = NewName;
}
void SetQuestionSize(){
Question.resize(15);
}
int ReturnQuestionSize(){
return Question.size();
}
void SetQuestion(){
Question[0]="Enter ";
Question[1]="1 ";
Question[2]="to ";
Question[3]="sort ";
Question[4]="in ";
Question[5]="ascending ";
Question[6]="order, ";
Question[7]="2 ";
Question[8]="for ";
Question[9]="Descending, ";
Question[10]="or ";
Question[11]="3 ";
Question[12]="to ";
Question[13]="ignore ";
Question[14]=EventName;
}
string ReturnQuestion(int Index){
return Question[Index];
}
/*vector<string> ReturnQuestion(){
return Question;
}*/
void SetMode(char NewMode){
if (NewMode == '0' || NewMode == '1' || NewMode == '2')
Mode = NewMode;
}
char ReturnMode(){
return Mode;
}
string ReturnName(){
return EventName;
}
};
This is will be a member of a second object, which will use Event's functions to store data in Event's members.
The problem I'm having is declaring an array of Event objects in my second object. When researching I came across ways to use an array of pointers to the first object, and some operator '->' that I'm guessing is related to virtual functions.
class WhatTheyWant{
Event *events[2];
public:
WhatTheyWant(){
events[0]= new Event("Miss");
events[1]= new Event("Dodge");
}
};
I'm very ignorant about pointers, and I know I will have to learn them eventually, but are they the best way to go or is there a better.
Since your Event class doesn't have a default constructor, you need to explicitly construct each object with its name, so the way you're doing it currently is the only way to do it.
If you add a default constructor to Event, you can do it in at least two other ways:
If you will always have a (small) fixed number of objects, you can just declare an array of constant size:
Event events[2];
Doing this will automatically construct the objects when WhatTheyWant is created, so you just need to set the names afterwards:
WhatTheyWant() {
events[0].SetName("Miss");
events[1].SetName("Dodge");
}
If you want to have a variable number of events, you can declare a single pointer and dynamically allocate an array of objects:
Event *events;
And you could probably give the number as a parameter to the constructor:
WhatTheyWant(int numEvents) {
events = new Event[numEvents];
for (int i = 0; i < numEvents; i++)
events[i]->SetName("...");
}
Also, not directly related to your question, but your Mode variable would be better modeled using an enumeration instead of a char. Using an enum makes it clearer as to what the variable really means, rather than using values like 0, 1 and 2. For example:
public:
enum ModeType { Ascending, Descending, None };
private:
ModeType Mode;
public:
Event() {
...
Mode = Ascending;
}
void SetMode(ModeType NewMode) {
Mode = NewMode;
}
ModeType ReturnMode() {
return Mode;
}
You can use either array of objects or array of pointers.
Array of objects go like below.
class WhatTheyWant{
Event events[2];
public:
WhatTheyWant()
{
events[0] = Event("Miss");
events[1] = Event("Dodge");
}
};
Note: You need to add default constructor to your event class to compile the above approach.
With the above approach, you do not need to take care of freeing Event objects. Whenever WhatTheyWant object gets destroyed, event objects get destroyed.
Array of pointers approach goes like you mentioned.
But you need to take care of freeing the memory allocated(Unless you use auto_ptr or some c++0x equivalent).
Deletion should happen in destructor like below.
class WhatTheyWant{
Event *events[2];
public:
WhatTheyWant(){
events[0]= new Event("Miss");
events[1]= new Event("Dodge");
}
~WhatTheyWant()
{
delete events[0];
delete events[1];
}
};
In C++, pointers are just like arrays
in your WhatTheyWant class, you define the private member:
Event *events[2];
This is an array of arrays (2D array) with variable length (of arrays) and 2 element in each array.
and the operator '->' is used when you want to access a (member of some kind of object) and that is called an object pointer (a pointer which points to an object) but when you define a normal object variable you use '.' operator.
If you've got the courage and knowledge to use them they are very useful but in general they're dangerous and that's why the new languages tend to go to the managed way.