I have a base class Toy and derived classes Toy_remote_car amd Toy_battery_car.
I am doing this:
Toy** ptr;
ptr=new Toy*;
ptr[0]=new Toy_remote_car[1];
ptr[1]=new Toy_battery_car[1];/*this is completely wrong according to my teacher because i never created ptr[1]. Instead this is a misuse of memory according to him.*/
The above code(ptr=new Toy*) is creating a single pointer of type Toy(ptr[0]) which contains the object of derived class Toy_remote_car.
Now i want to write such a code:
->the number of Toy type pointers should not be predefined.
->instead i would call an add_toy function which would create a ptr that will point to the type of object i want. Furthermore if i call the add_toy function again, it should not assign the data to the previos ptr, but it should create a new ptr. The following convention may help:
ptr[0]=new Toy_remote_car[1];
/*we want to add more toys so add_toy function called. A check is applied.*/
/*The check checks that ptr[0] already contains a value so it creates another pointer ptr[1]*/
ptr[1]=new Toy_battery_car[1];
->furthermore i would be able to access all the previous data. In short:
ptr[0]//contains one type of data.
ptr[1]//contains another type.
//and so on
->so it would automatically create a pointer(ptr) of type Toy whenever a new Toy is being added.
I hope i have explained well what i am trying to implement in this code.
Please please help me in this regard.
Thanks
Toy **ptr = new Toy *[n];
where n holds the number of Toy pointers you want. Growing the array is hard, but it can be done:
// Add x to toypp, an array of n pointers
// very stupid, linear-time algorithm
Toy **add_toy(Toy *x, Toy **toypp, size_t n)
{
Toy **new_toypp = new Toy*[n+1];
// copy the old array's contents
for (size_t i=0; i<n; i++)
new_toypp[i] = toypp[i];
toypp[n] = x;
// clean up
delete[] toypp;
return new_toypp;
}
Note the if the allocation fails, the old toypp and all pointers in it are not cleaned up. Really, if you want an array that grows, use a vector<Toy*> instead:
vector<Toy*> toy_ptrs(n);
and add toys with push_back.
Don't forget to delete every single Toy*, and with the first method, to delete[] the Toy**.
Handling various kinds of data can be done with inheritance.
I have come up with this code with a very simple logic. And this is working completely fine. Please give a look and do give opinions.
void add_toy_var()
{
temp=NULL;
temp=tptr;
tptr=NULL;
delete[] tptr;
C1.count1++;
tptr=new Toy*[C1.count1];
if(temp!=NULL)
{
for(int i=0; i<(C1.count1-1); i++)
{
tptr[i]=temp[i];
}
}
int choice2;
cout<<"Which Toy you want to add?"<<endl;
cout<<"1. Remote Toy Car"<<endl;
cout<<"2. Batt powered toy car"<<endl;
cout<<"3. Batt powered toy bike"<<endl;
cout<<"4. Remote control toy heli"<<endl;
cin>>choice2;
if(choice2==1)
{
tptr[C1.count1-1]=new Toy_car_rem[1];
tptr[C1.count1-1]->set_data();
}
else if(choice2==2)
{
tptr[C1.count1-1]=new Toy_car_batt[1];
tptr[C1.count1-1]->set_data();
}
else if(choice2==3)
{
tptr[C1.count1-1]=new Toy_bike_batt[1];
tptr[C1.count1-1]->set_data();
}
temp=NULL;
delete[] temp;
}
Related
I am creating a grid game in which each box in the grid is a district and represents some people along with their specific ID.
Now I have a function here which locates where the exact person is in the grid in particular box.
Here is my function.
bool where(int id, int &row, int &col)const
{
person* per;
for(int i=0;i<alive.size();i++)
{
std::cout<<alive[i]<<std::endl; //This is just for testing the person number
if (alive[i]->person_id == id)
{
p = alive[i];
break;
}
}
}
My Question: The test code std::cout<<alive[i]<<std::endl; is always printing the address of the number. I tried many things but I couldn't figure it out.
Edit: Here alive is a vector
Can anyone please help me.
Consider this line in your code: if (alive[i]->person_id == id). The fact that it uses -> rather than . indicates that alive isn't a vector of some struct/class, but is rather a vector of pointers (or potentially some other object that acts like a pointer) to some struct/class. As such, to print the actual object, do std::cout<<*alive[i]<<std::endl; (note the added *).
In this situation, I want to delete book, but I try declare this code, its not working.
class Library {
private:
Book **books;
int counter;
public:
Library() {
books = NULL;
counter = 0;
}
void Add(INPUT &tmp) {
books = new Book*[counter];
++counter;
}
void Delete() {
--counter;
delete[] books[counter];
books[counter] = NULL;
}
int getCounter() {
return this->counter;
}
~Library() {
delete[] books;
}
};
Before you get deleting to work, you need to get adding right.
In addition to what Jeffrey said, your Add function probably doesn't work correctly due to an "out by one" error. In the first call you will have books = new Book*[0];. Allocating a zero sized array is legal (see here) but you will not be able to store anything in it.
If you can use a std::vector it will make your code much simpler and less error prone.
class Library {
private:
std::vector<Book> books;
// no need for counter, std::vector has size()
public:
// no need for a constructor, the default constructor
// will correctly construct 'books'
void Add(INPUT &tmp) {
// not sure how you convert 'INPUT' to 'Book'
books.push_back(tmp);
// this handles all of the memory management for you
}
void Delete() {
// you need to ensure that books is not empty
books.pop_back();
}
int getCounter() {
return books.size();
}
// no need for a destructor, the default one will
// do everything
};
If you need two dimensions, then the code is similar but will use a vector of vector.
Book **books;
is a pointer to a pointer to a book. It is the old style way of having a list of books (as pointers) or a list of list of books.
Library() {
books = NULL;
counter = 0;
}
This will create an empty library. No books.
void Add(INPUT &tmp) {
books = new Book*[counter];
++counter;
}
First thing to notice is that you are not using the tmp book. So you probably won't succeed in storing it anywhere, without using it.
Second thing is that books = new Book*[counter]; allocates a library of books. Space for storing some books. You probably should do that in the constructor. If you do it there, every time you try to add a book, you'll lose all the others, and you'll also leak memory.
There's two possibilities here. You have an old-timer C++ professor, and you'll need to learn about pointers and pointers to pointers, and new, delete. Or you could learn about std::vectors and smart-pointers. This would be a better idea, but I can't tell you how well it will be received in your class.
Also, please state what INPUT is defined as.
I am new to c++(have a java background) and thus pointers are sort of new to me. I am dealing with an array of pointers where each index points to an object on the heap as so:
Deck::Deck()
{
seed = rand()%100; //this will be used in shuffle method
srand(seed);
for(int i=0;i<deckSize;i+=3) //deckSize=12 in this case, p defined as CardTypes* p[deckSize]
{
p[i]= new Infantry();
p[i+1] = new Artillery();
p[i+2] = new Cavalry();
}
}
All 3 of these classes are subclasses of the class CardTypes(which was only created so I could store diff types in an array).
class CardTypes
{
public:
virtual string getCard() = 0;
virtual ~CardTypes() {};
};
class Infantry: public CardTypes
{
const string name = "Infantry";
public:
string getCard(); //this simply returns "name" so that I can differentiate each object in the array by a data value
};
class Artillery:public CardTypes
{
const string name= "Artillery";
public:
string getCard();
};
class Cavalry:public CardTypes
{
const string name = "Cavalry";
public:
string getCard();
};
Although not a great way to do it, I have created another array of pointers(CardTypes* s[deckSize) which copies pointers from p into s randomly(thus mimicking a shuffle in a deck of cards):
void Deck::shuffle() //this is the method that puts objects in s to be grabbed in draw()
{
int j = 0;
int k = 1;
int l = 2; //initial setup(index 0 will have Infantry, index 1 will have Artillery and index 3 will have Cavalry and this pattern continues throughout p)
int n = rand()%3 + 1; //gives random # between 1 and 3 1=infantry,2 = artillery,3 = cavalry
int i=0; //counter for loop
while(i<deckSize)
{
n = rand()%3+1;
if(n==1)
{
if(j>9) //means no more infantry cards as due to pattern of p
infantry cards stop after index 9
{
continue; //used to reset loop foranother iteration(will get random number,I know this is bad for time complexity)
}
else
{
s[i] = p[j]; //copy "Infantry" pointer to s
j+=3;
i++;
}
}
else if(n==2)
{
if(k>10)//means no Artillery cards due to pattern in p
{
continue;
}
else
{
s[i] = p[k];//copy "Artillery" pointer to s
k+=3;
i++;
}
}
else
{
if(l>11) //means no more cavalary cards due to pattern in p
{
continue;
}
else
{
s[i] = p[l]; //copy "Cavalry" pointer to s
l+=3;
i++;
}
}
}
}
Now my issue is i am trying to create a draw method that grabs a pointer from s and returns it. My program completely crashes when I attempt this and I am not sure why:
CardTypes* Deck::draw() //draws a card from the deck and returns it
{
CardTypes* card = s[deckSize];
delete s[deckSize];//clear heap
s[deckSize] = NULL;//remove what pointer was pointing too (as card has been drawn)
deckSize--;
return card;
}
I then attempt to call this method:`
int main()
{
Deck d1;
d1.shuffle(); //this works
d1.getCurrentDeck();//this works, just prints out each objects getCard() method in s
CardTypes* card = d1.draw();//does not cause a crash
cout<<"Card:"<<card->getCard() <<"\n";//crashes here
}
This issue is probably due to my inexperience with pointers but any help would be appreciated. Also note I delete the arrays after I am done with the program using delete [] p and delete [] s, I have not included this in the code as it is not of issue right now.
You are struggling with pointer ownership. You understand that in C++ one must delete a pointer when it is no longer needed, but in Deck::draw you delete a pointer when it is still needed.
CardTypes* Deck::draw()
{
CardTypes* card = s[deckSize]; // s and card point to same allocation
delete s[deckSize]; // boom! card points to garbage.
s[deckSize] = NULL;
deckSize--;
return card;
}
You can use raw pointers, but you need to do it with a lot of coding maturity and deliberation.
Or you can say Smurf it and protect yourself from accidents like this with smart pointers. What is a smart pointer and when should I use one?
std::unique_ptr bundles ownership of a pointer. Only one std::unique_ptr is allowed at a time. You can't copy it. It as to be moved everywhere, transferring ownership from one holder to the next. But in the end there can be only one. You have to go out of your way to be stupid with a unique_ptr. Making five unique_ptrs and pointing them all at the same pointer, yeah you can do that. Put a self-destructing Automatic variable in a unique_ptr, yeah you can do that (and sometimes you do, but with a custom deleter that does nothing).
unique_ptr is the owner of the pointer. Whoever has the unique_ptr is owner by proxy because as soon as they get rid of the unique_ptr, the pointer goes with it.
Let's take a look at what we can do with a std::unique_ptr<CardTypes> to corral these wild pointers. If s is an array of unique_ptrs, std::unique_ptr<CardTypes> s[MAX_DECK_SIZE];, draw becomes
std::unique_ptr<CardTypes> Deck::draw()
{
std::unique_ptr<CardTypes> card = std::move(s[deckSize]);
// delete s[deckSize]; don't. Card now owns the card
// s[deckSize] = NULL; handled by moving ownership
deckSize--;
return card;
}
This can be simplified to
std::unique_ptr<CardTypes> Deck::draw()
{
return std::move(s[deckSize--]);
}
decksize-- is a post decrement so it happens after and the rest of the work is managed by the unique_ptr when it is moved out of s;
Sadly this means
s[i] = p[j];
ain't so easy anymore. You need
s[i] = std::move(p[j]);
But only if p no longer needs its jth element, because s[i] owns it now, baby.
Too little information has been provided in the question to wrangle this properly, but...
It's very possible that you could keep p full of unique_ptrs and load s with raw pointers whose lifespan is governed by p and pass s's pointers around naked and free without ever deleteing them because you know p has your back. So long as you keep p around longer than s and whoever s gives pointers to. It all comes back to ownership and in this case p owns all the Cards.
That turns
s[i] = std::move(p[j]);
into
s[i] = p[j].get();
and draw into
CardTypes * Deck::draw()
{
return s[deckSize--];
}
and makes life really, really easy.
Your problem is you are deleting the instance and, after that, you want to use it.
You are creating many instances:
for(int i=0;i<deckSize;i+=3) //deckSize=12 in this case, p defined as CardTypes* p[deckSize]
{
p[i]= new Infantry();
p[i+1] = new Artillery();
p[i+2] = new Cavalry();
}
The size of your array is determined by the variable deckSize.
In your function Deck::draw() your have some errors:
You are set a pointer of an instance of CardType with this code: CardTypes* card = s[deckSize]; But the array s has an index base 0, so s[deckSize]is accessing another memory sector that is not assigned to array s (Could a Memory Access Violation). use s[deckSize-1] instead of s[deckSize]..
You are release the memory that was assigned to pointer card and this pointer is returned to be used outside the function, which try to use this instance but is doesn't exist any more. So the memory which card and s[deckSize] share is released. Don't forget that s[deckSize] could raise a Memory Access Violation.
Check your code:
CardTypes* Deck::draw() //draws a card from the deck and returns it
{
CardTypes* card = s[deckSize-1]; //Assign the pointer to card.
delete s[deckSize-1];//DELETE THE INSTANCE (The memory that
return card; //The card points to a memory previously released.
}
Here is the moment that you are trying to use an unallocated:
CardTypes* card = d1.draw();//Get the pointer to s[deckSize-1]
cout<<"Card:"<<card->getCard() <<"\n";//crashes here
UPDATE:
Answer your comment, You can do this:
1.- Get the referencer to instance: CardTypes* card = s[deckSize-1];.
2.- Set the slot of your array in NULL and decrease the index:
s[deckSize-1]=NULL;
deckSize--;.
3.- Return de reference saved in card to upper level: return card;.
4.- Use the reference returned as you need it:
CardTypes* card = d1.draw();
cout<<"Card:"<<card->getCard() <<"\n";.
5.- Finally, delete de instance once you have finished to use it, for example just after the invocation of getCard():
cout<<"Card:"<<card->getCard() <<"\n";
delete card;
It's important to say that you decide where and when reserve, use and release the memory; just keep in mind to do it in an organized way and apply best practices, like these:
https://www.codeproject.com/Articles/13853/Secure-Coding-Best-Practices-for-Memory-Allocation
http://www.embeddedstar.com/technicalpapers/pdf/Memory-Management.pdf
I'm a c++ student and this is my second post here. I'm working on a class whose job is to maintain an array of object pointers. (That way a pointer can be passed in and added to the array, instead of the entire object.)
The array is supposed to be dynamic but I'm running into some errors when I try to dynamically allocate memory for it. The following code produces the error "expression must be a modifiable lvalue" at studArray, as marked.
#ifndef MYCLASS_H
#define MYCLASS_H
#include "Student.h"
class myClass{
private:
Student* studArray[5];
int howMany;
int max;
public:
myClass(){
Student firstOne;
studArray[0] = &firstOne;
howMany=0;
max=5;
}//myClass()
void insertEl( Student* nextEl ){
howMany++;
if(howMany >= max){
Student** tempPt = new Student* [max + 1];
for( int i = 0; i < currentNum; i++){
tempPt[i] = studArray[i];
}
delete [] studArray;
studArray = tempPt; // <-------------------------error
}
studArray[ howMany ] = nextEl;
}//insertEl
};
I tried changing the original Student * array to have no size specified, but that produced the error "incomplete type is not allowed" at studArray.
class myClass{
private:
Student* studArray[]; <------------- error
int howMany;
int max;
What am I doing wrong?
(Thank you for the help!)
For reference I'm using Win 7 64bit, Visual Studio Professional 2012.
Assumptions: Instructor want you to learn the fine art of memory management on your own. So no library containers and no smart pointers. When you have the time, look into how to use the standard containers and the smart pointers. They'll save you a huge amount of time and grief in the future.
First, declaring the Student array.
Student* studArray[5];
You have the crux of it right here
Student** tempPt = new Student* [max + 1];
So try
Student** studArray;
And then hack your constructor to allocate the storage
myClass()
{
max = 5;
studArray = new Student*[max]; /* For improved safety, read up on
exceptions, catch and handle the
out of memory exception */
howMany = 0;
} //myClass()
I recommend adding a destructor to handle the clean up and put back your array.
virtual ~myClass()
{
delete[] studArray;
}
Check with the assignment notes or the instructor to see who is responsible maintaining the Students. You may have to revisit the destructor to delete all of the Students before deleting studArray
Additional note:
myClass()
{
Student firstOne;
studArray[0] = &firstOne;
howMany=0;
max=5;
}//myClass()
Student firstOne; is a temporary variable. firstOne only exists between the closest enclosing {} braces. This is called Scope. Using any value outside of it's scope will have unpredictable results and most likely crash the program. Frankly, that's if you are lucky. The program may limp on for some indeterminate time and crash later.
The assignment studArray[0] = &firstOne; is dangerous because by the time anyone tries to use studArray[0], the data at which it points will not be valid. firstOnedoes not exist outside the constructor. If you want firstOne to go on living, you will have to define it as a pointer, create it with new, and delete it when it is no longer needed. In this case I don't think you ever need it.
Another suggestion is to double the size of studArray rather then simply adding one when it is full. This way you don't have to reallocate the storage and copy all of the existing students to the new storage as often.
A better method is to have a std::vector of Student:
std::vector<Student *> maleStuds;
std::vector<Student *> femaleStuds;
Or, if you must use arrays:
const unsigned int MAXIMUM_STUDENTS = 5;
Student * students[MAXIMUM_STUDENTS];
For dynamic:
Student * * students = new Student * [MAXIMUM_STUDENTS];
So say I have
Class Person{
private:
Person* _friends[10];
public:
//All methods listed below. Except for the main one, that is.
}
Person::Person()
{
for(int i=0; i < 10; i++)
_friends[10] = 0;
}
Person* Person::getFriends()
{
return _friends;
}
void Person::addFriend(Person* buddy) //Assume it's fully functional.
{
//code for adding a friend.
}
void Person::operator=(Person& p)
{
for(int i = 0; i < 10; i++)
_friends[i] = p.getFriends()[i];
}
int main()
{
int user1size = 10;
int user2size = 30;
Person* user1 = new Person[10];
Person* user2 = new Person[10];
//assume these 4 next lines will be repeated with different values a few more times, in more intricate ways, by the magic of for/while loops.
user1[0] = new Person();
user2[9] = new Person();
user1[0].addFriend(user[9]);
user1[9].addFriend(user[0]);
for(int i = 0; i < user1size; i++)
{
user2[i] = user1[i]; //Here is where the paradox starts.
}
delete [] user1;
return 0;
}
So well, my question is where does it stop? I mean, my intent is to only copy the reference to the Person objects inside the _friends array, but I understand that might be little to no possible, so the solution is to keep "copying" these Person objects too, who in turn also have a list of friends, and these friends also have friends and so on. I know it has to stop somewhere, but I don't really want it to go all the way through and not to even mention I don't want some Person objects to be over-copied or catch in an infinite loop.
so how to solve this paradox?
P.S. : Please understand if my code has a lot of mistakes or is crappy. I made it in the go and all I intend with it is to make you all catch the general idea.
P.S.2: I cannot use any other library other than <ostream>, yup sucks for me.
P.S.3: Any website/article you could provide me to read about this would make me so happy! Thank you beforehand.
Well, first of all, what you probably want to do is to just copy the pointers as they are.
Why? Because if person "A" has a friend "F", and person "B" has the friend "F" as well, they will probably refer to the same person "F" object. If you make a deep-copy as you suggested, and you copy A to A2 and B to B2, you will have a total of three distinct person "F" objects -- the original, referenced from A and B, a copy referenced from A2, and another copy referenced from B2.
Of course, this might be what you want; I can't know that. But in many cases it's not.
The whole pointer setup will work just fine, although you have to be careful with memory management: you can easily end up with pointers to persons that no longer exist
If you do want to do a deep copy (a "deep copy" is a copy where referenced objects are copied too) you'll have to find cycles yourself, for example by tracking which objects you have copied already. I won't be trying to sketch something like this now, as it can get somewhat complicated and I don't think you actually want to deep copy your "person" objects.
There is no paradox because you are not doing a deep copy. Check out this declaration:
Person* _friends[10];
This says _friends is an array of pointers to Person objects. Correctly copying in operator=() this array will not call operator=() on each Person in the array.
However, the following function will not compile:
Person* Person::getFriends()
{
return _friends;
}
The return type and the type of _friends does not match. This is why it is important to post code that compiles and exactly reproduces the problem you have encountered.
IIUC, you want to know how to handle copies of graphs of objects, and you want to maintain their connections in the graph. Let's say Joe has a friend Bill and Bill has a friend Joe, and you copy Joe (lets name the copy Joe'), you want Joe' also have a friend who has (reflexively) Joe' as a friend. This problem typically comes up when programming compilers.
The easiest way to actually do this is never do any copies. Let the objects reside in their memory locations, use references/pointers to them all the time and modify them destructively.
However, it is sometimes needed to copy the objects, possibly modifying the graph (in the compiler scenario, that might mean eg. inlining a function). In that case, you employ a simple graph traversing algorithm, the DFS, roughly like this:
// o will be the object to copy
// m will be a map (old object -> new object)
copy(object* o, map& m) {
if(m.contains(o))
return m[o];
object* n = allocate new object;
m[o] = n; // set the map beforehand, in case we have some back edges from this subtree
n.subobject = copy(o.subobject, m); // for each subobject, or relation. In your case, friend
return n;
}
If you want just to move some object to a new location, you can just traverse the whole graph and overwrite the pointers. This is much easier if you have back edges in your graph, too (ie. not only "friends", but also "people whose friend I am"). Still, the best option is to avoid it; that means not creating arrays of Persons that might grow and make arrays of Person*s, so that the real Person still stay in the same memory location.