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.
Related
Let's assume I got an abstract class ("Book" in the example below) and some derived classes ("ElectroniBook","CodingBook" in the example below). I also want to keep a vector of books in a third class ("Library") and some maps to find them. Let's also assume that I need to create the "Library" from somewhere else using the "addBook" method and then assign it in the main.
Since Book is abstract I eventually need to delete the "Book" pointers I created and I want to do it in some destructor. Neverthless, whenever I try to use delete i got this error message
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
and if I try to replace raw pointers with shared_pointers or unique_pointers I immediately get errors at compile time telling me I'm trying to use pointers that have already been deleted. Note that I'm using C++ 11.
Here's some code just for example :
class Book{
public:
Book(string name, int Npages);
virtual ~Book();
virtual void displayBook() = 0;
private:
string _name;
int _Npages;
}
class ElectronicBook : public Book{
public:
ElectronicBook(string name, int Npages);
~ElectronicBook();
void displayBook() { //do something
};
}
class CodingBook : public Book{
public:
CodingBook(string name, int Npages);
~CodingBook();
void displayBook() { // do something else
};
}
class Library{
public :
Library();
~Library(){
// this doesn't work for me
// for(auto & a : _books)
// delete a;
// _books.clear();
//
//for(int i=0;i<_bookmap.size();++i)
// delete bookmap.at(i);
};
void addCodingBook(string name, int Npages){
CodingBook* cb = new CodingBook(name, Npages);
_books.push_back(cb);
_bookmap[name] = cb;
//should I delete anything here?
};
void addEletronicBook(string name, int Npages){
ElectronicBook* eb = new ElectronicBook(name, Npages);
_books.push_back(eb);
_bookmap[name] = eb;
//should I delete anything here?
};
private :
vector<Book*> _books;
map<string, Book*> bookmap;
}
// separeted function
Library createLibrary(){
Library L;
while(...){
//read books from somewhere(file, input or whatever) and
// addElectronicBook(...)
// addCodingBook(...)
}
return L;
}
int main(){
Library myLibrary = createLibrary();
// do something with Library
}
Since I did several times "new" to add Books, I need to delete them. I tried to do it in the Library destructor like I showed but I got the error mentioned before.
If I understand correctly your issue, you are freeing twice the same memory:
// for(auto & a : _books)
// delete a;
// _books.clear();
//
//for(int i=0;i<_bookmap.size();++i)
// delete bookmap.at(i);
Both _books and bookmap contain pointers that are pointing to the same ares of memory and you are freeing them twice.
When working with raw pointers you have to decide who is the owner of the memory, say, for example _books and who has simply access to the memory but is not responsible for the cleanup.
So, you should:
delete only once, so use only one of the two for loops, say for the sake of argument _books
make sure that the other non-owning structures, say bookmap in our example, never, ever access the memory (i.e. de-reference the pointer) after the deletion
Suggestion: put in the vector unique_ptr so the vector is the owner and put raw pointers in the map to signal that the map is not owning. unique_ptr will take care of cleaning up the memory for you. If you want to be sure, add some print statements or put break points in the destructors if you have a debugger.
I'm new to this website and will try to contribute just as much as I ask. Also, please know I never ask a question without spending much time trying to figure it out myself.
As such, C++ Stacks are driving me f***ing crazy.
My Question: where do I place my variables/values in the Stack function block to actually use it. I understand Stacks are a LIFO data-structure, I've read countless examples of stacking plates on top of each other, etc.
Look at this code:
#include <iostream>
using namespace std;
const int MAX_SIZE = 100;
class StackOverFlowException
{
public:
StackOverFlowException()
{
cout << "Stack overflow" << endl;
}
};
class StackUnderFlowException
{
public:
StackUnderFlowException()
{
cout << "Stack underflow" << endl;
}
};
class ArrayStack
{
private:
int data[MAX_SIZE];
int top;
public:
ArrayStack()
{
top = -1;
}
void Push(int element)
{
if ( top >= MAX_SIZE )
{
throw new StackOverFlowException();
}
data[++top] = element;
}
int Pop()
{
if ( top == -1 )
{
throw new StackUnderFlowException();
}
return data[top--];
}
int Top()
{
return data[top];
}
int Size()
{
return top + 1;
}
bool isEmpty()
{
return ( top == -1 ) ? true : false;
}
};
[etc....]
It's basic cookie-cutter....let's say I'm trying to adapt it to express a system where the last food orders placed in, are kicked out first; variables are 'food', 'orders', and whatever else.
Where in the world am I integrating those variables into that stack code above!?!??!
Please help so confused i'm about to indiscriminately punch something
A stack implementation could use templates so that you could put whatever you want in the stack (within reason).
For example, have a class that encapsulates all the data related to orders (this one is just an example):
class FoodOrder
{
int orderNumber;
time_t orderTime;
// add more variables here
}
Then, your stack could look like this:
template<typename T> class Stack
{
T data[MAX_SIZE];
int top;
void Push(T item);
T Pop(void);
// add methods
}
Then, you could have a Stack of whatever items you want:
Stack<int> stackOfInts;
Stack<std::string> stackOfStrings;
Stack<FoodOrder> stackOfOrders;
Use the existing std::stack and wrap it if you want the exceptions, for example like this (note you could easily templatize it):
class protectedstack
{
private:
std::stack<int> stack;
const int myarbitraryupperlimit = 100;
public:
void pop()
{
if(stack.empty())
{
throw new StackUnderFlowException();
}
stack.pop();
}
void push(const int& value)
{
if(stack.size()>=myarbitraryupperlimit)
{
throw new StackOverFlowException();
}
stack.push(value);
}
// Similar for top/empty/constructors/...
};
The type of data, as well as that of what Top & Pop return, and what Push takes as an argument, is what is contained in the stack; that's what you'd replace w/ the type of whatever you want to make this a stack of.
This is a stack:
Think of it this way: the only way to add a book without moving the others is to place it on top : this is what Push does. So by calling Push(Book1), you'd be placing Book1 on top of the pile.
Similarly, the only way to take away a book without moving the others is to take the one on top : this is what Pop does. So by calling Pop(), you'd be getting (and removing from the stack) whichever book is on top of the stack, which in the image is the green book.
Am I missing something or was this your question?
It's all in the top variable. This variable dictates which object is the current top. When you pop(), then the top variable is reduced- meaning that the top is now one below where it was. When you push(), it's incremented- the top is now one above where it was. This variable is what accounts for the LIFO functionality of the stack.
You can, of course, template the class to make it work with a FoodOrder or whatever.
I don't see why the confusion. The data would go in, duh!, the "data" variable.
So, you either use Templates, to make the data buffer able to hold anything, or you change the type of the data to what you specifically need.
If for example you have a FoodOrder class, you can do it like this (my C++ is rusty, but this is basically the gist of it):
FoodOrder *data[MAX_SIZE];
You would have to change the push/pop parameters to accept a FoodOrder pointer/reference accordingly, and you're set.
P.S. About using std::stack --this might be a better solution, but doesn't answer his specific question.
P.S 2 Poster writes: "I'm new to this website and will try to contribute just as much as I ask.". Really? So why hasn't he even picked an answer yet? Does this smell more like a homework assignment?
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;
}
I have a vector with raw pointers (no, I cannot use smart pointers) and I want to add items to the list in a for loop. I've made a little trial project, and I wondered if this is considered good C++ code in terms of pointer management.
Please only consider raw pointer management, I am not interested in smart pointers for this particular problem I'm trying to solve.
A simple object:
class Request
{
public:
std::string name;
};
std::vector<Request*> requests;
for (int i = 0; i < 5; i++)
{
std::stringstream ss;
ss << "elemenent ";
ss << i;
std::string s = ss.str();
Request* req = new Request();
req->name = s;
requests.push_back(req);
}
EDIT:
So the problem I am trying to solve is adding the DOMNode* to a vector from this library.
I'm starting to get the feeling that trying to write a wrapper for the parts I need from this library for my project, is a bad idea. Or maybe the library is no good?
I haven't got it to work properly using smart_ptr, if anybody out there has, then I'd like to hear about it.
Well, this leaks memory, so it is bad. Can you use a Pointer Container?
The reason this code leaks is because you create objects on the heap using new, but you never call delete on them.
As for you comment, if you have an object that manually manages some resource, you need The Big Three.
I'll consider that you have a loop, at the end of the method, to call delete on each member of the vector.
There are still issues, specifically exception safety issues.
If anything throws between the creation of the Request and its registration in the vector, you've lost the memory. One solution is to temporarily use a scoped_ptr to hold on the memory, push_back with ptr.get() and then call the release method since now the memory is owned by the vector.
If anything throws between the point when you have created the items in the vector and the point you destroy them, you need to catch the exception, destroy the items, and then rethrow.
There might be others, but RAII has been invented for a reason, it's really difficult to do without (correctly...)
If you cannot use smart pointers, then use boost::ptr_vector.
Note that if you are using TinyXml, memory management in XmlNode is probably dictated by the library - recent history iirc is that many of your problems are associated with properly understanding the memory ownership and release paradigm for this library.
What memory management do I need to cleanup when using TinyXml for C++?
What is the best open XML parser for C++?
If you are not able (or allowed) to use smart pointers, probably you could make use of a simple memory manager like this:
template <class T>
class MemManager
{
public:
typedef std::vector<T*> Vec;
~MemManager ()
{
size_t sz = v_.size ();
for (size_t i = 0; i < sz; ++i)
delete v_[i];
}
T* pushNewObject ()
{
T* t = NULL;
try
{
t = new T;
if (t != NULL)
v_.push_back(t);
}
catch (std::bad_alloc& ex) { /* handle ex */ }
return t;
}
const Vec& objects() const { return v_; }
private:
Vec v_;
};
// test
{
MemManager<Request> mm;
for (int i = 0; i < 5; i++)
{
std::stringstream ss;
ss << "elemenent ";
ss << i;
std::string s = ss.str();
Request* req = mm.pushNewObject();
req->name = s;
}
} // all Request objects will be deleted here when
// the MemManager object goes out of scope.
A quick improvement could be to derive a class RequestVector from std::vector<Request*>, add a ClearRequests method (which deletes all the Request objects and clears the vector) and and make it's destructor call ClearRequests.
(Actually aggregating the vector in RequestVector could be a better choice, but a derived class is faster done).
I have developed an array based implementation of a hashTable with several stock names, symbols, prices, and the like. I need to remove a stock from my array. I am told that using the delete operator is bad object oriented design. What is the good object oriented design for deletion?
bool hash::remove(char const * const symbol, stock &s,
int& symbolHash, int& hashIndex, int& usedIndex)
{
symbolHash = this->hashStr( symbol ); // hash to try to reduce our search.
hashIndex = symbolHash % maxSize;
usedIndex = hashIndex;
if ( hashTable[hashIndex].symbol != NULL &&
strcmp( hashTable[hashIndex].symbol , symbol ) == 0 )
{
delete hashTable[hashIndex].symbol;
hashTable[hashIndex].symbol = NULL;
return true;
}
for ( int myInt = 0; myInt < maxSize; myInt++ )
{
++usedIndex %= maxSize;
if ( hashTable[usedIndex].symbol != NULL &&
strcmp( hashTable[usedIndex].symbol , symbol ) == 0 )
{
delete hashTable[usedIndex].symbol;
hashTable[usedIndex].symbol = NULL;
return true;
}
}
return false;
}
Noticing that i have a stock &s as a parameter, i can use it like this:
s = &hashTable[usedIndex];
delete s.symbol;
s.symbol = NULL;
hashTable[usedIndex] = &s;
This does work however, it results in a memory leaks. Even then, i am not sure if it is good object orinted design.
here is my header, where stock and all that stuff is initialized and defined.
//hash.h
private:
friend class stock;
int isAdded; // Will contain the added hash index.
// Test for empty tables.
// Can possibly make searches efficient.
stock *hashTable; // the hashtable will hold all the stocks in an array
};
// hashtable ctor
hash::hash(int capacity) : isAdded(0),
hashTable(new stock[capacity]) // allocate array with a fixed size
{
if ( capacity < 1 ) exit(-1);
maxSize = capacity;
// We can initialize our attributes for the stock
// to NULL, and test for that when searching.
for ( int index = 0; index < maxSize; index++ )
{
hashTable[index].name = NULL;
hashTable[index].sharePrice = NULL;
hashTable[index].symbol = NULL;
}
}
// stock.h
...
friend class hashmap;
private:
const static int maxSize; // holds the capacity of the hash table minus one
date priceDate; // Object for the date class. Holds its attributes.
char *symbol;
char *name;
int sharePrice;
};
My question is still just, how do i preform a safe remove?
s = &hashTable[usedIndex];
delete s.symbol;
s.symbol = NULL;
hashTable[usedIndex] = &s;
That seems to work, but results in memory leaks! How is this done safely?
delete hashTable[usedIndex].symbol;
hashTable[usedIndex].symbol = NULL; <-- without doing this.
The status of the slot in the array (empty, etc) should not be recorded in the stock instance. That's bad object oriented design. Instead, I need to store the status of an array slot in the array slot itself.
How would i do that?
NOTE: This answer is just addressing
some of the things you are doing
incorrectly. This is not the best way
to do what you are doing. An array of
stock** would make more sense.
Doesn't your stock class have a constructor? You don't need to know anything about the stock class if it is a proper object:
hash::hash(int capacity) // change this to unsigned and then you can't have capacity < 0
: isAdded(0)
, hashTable(0) // don't call new here with bad parameters
{
if ( capacity < 1 ) exit(-1); // this should throw something, maybe bad_alloc
maxSize = capacity;
hashTable = new stock[capacity]; // this calls the stock() constructor
// constructor already called. All this code is useless
// We can initialize our attributes for the stock
// to NULL, and test for that when searching.
// for ( int index = 0; index < maxSize; index++ )
// {
// hashTable[index].name = NULL;
// hashTable[index].sharePrice = NULL;
// hashTable[index].symbol = NULL;
// }
}
class stock {
char* name; // these should be std::string as it will save you many headaches
char* sharePrice; // but I'll do it your way here so you can see how to
char* symbol; // avoid memory leaks
public:
stock() : name(0), sharePrice(0), symbol(0) {}
~stock() { delete[] name; delete[] sharePrice; delete[] symbol; }
setName(const char* n) { name = new char[strlen(n)+1]; strcpy(name, n); }
setPrice(const char* p) { sharePrice = new char[strlen(p)+1]; strcpy(sharePrice, p); }
setSymbol(const char* s) { symbol = new char[strlen(s)+1]; strcpy(symbol, n); }
const char* getName() const { return name; }
const char* getPrice() const { return sharePrice; }
const char* getSymbol() const { return symbol; }
}
To get good object oriented design, a collection should be agnostic of what is stored in it. This really has nothing to do with using the delete operator per se, but requiring an object (your stock in this case) to store data structure specific code is.
There are two plans things I can see to quickly fix this issue.
Use an array of stock * instead of just stock. Then a null value will mean the slot is open, and a non-null value will mean the slot can be used. In this plan you would call new and delete on the entire stock object as it is inserted and then as it is removed, which is more object oriented than just the symbol.
Create a HashSlot class that wraps the stock item, adding the book keeping values that are needed.
Your hash table would then be an array of HashSlot items.
I prefer the second. In either case, stock should have a destructor that clears up its own internal memory.
It looks like you're using (or trying to use) open addressing with linear-probing for collision resolution. In that case, you need to somehow mark items as deleted (as opposed to empty), so that you can still access items which fall after deleted items. Otherwise, you won't be able to lookup certain items because your probing sequence will be terminated prematurely if it finds a deleted bucket. Therefore, you won't be able to access certain items in the table anymore and that's probably why you're getting a memory leak.
Basically, you're supposed to start at the hash index, compare the item with your key, and then if it isn't equal to your key, increment to the next index and repeat until either you find the item, or until you encounter an empty bucket. If you find the item, delete the item and mark that index as deleted. But the important thing is that you have some way to distinguish between an empty hash bucket, and a deleted hash bucket, otherwise a deleted bucket will cause you to terminate your probing sequence early.
As for "good object oriented design", there is no inherent property of object-oriented programming that necessarily makes using delete a bad design. Every data structure that allocates memory has to free it somehow. What you're probably referring to is the fact that it's usually safer and less work to implement classes that don't manage their own memory, but rather delegate that responsibility to pre-made container classes, like std::vector or std::string
I have developed an array based implementation of a hashTable with several stock names, symbols, prices, and the like. I need to remove a stock from my array. I am told that using the delete operator is bad object oriented design. What is the good object oriented design for deletion?
Well, one of the key principles behind object oriented design is reusability.
Hence, the only good object oriented design is to reuse the solutions that have already been developed for you!
C++ comes with a perfecetly good map class. Most recent compilers also support TR1, which adds a hash table under the name unordered_map.
The Boost libraries also contain an implementations of unordered_map in case you're stuck on a compiler without TR1 support.
As for your question about delete:
I'm not sure who told you that delete is "bad object-oriented design", or why, but what they might have meant is that it is bad C++ design.
A common guideline is that you should never explicitly call delete. Instead, it should be called implicitly through the use of the RAII idiom.
Whenever you create a resource that must, at some later point, be deleted, you wrap it in a small stack-allocated object, whose destructor calls delete for you.
This guarantees that it gets deleted when the RAII object goes out of scope, regardless of how you leave the scope. Even if an exception is thrown, the object still gets cleaned up, its destructor called, and your resource deleted. If you need more complex ways to manage the object's lifetime, you might want to use smart pointers, or just extend your RAII wrapper with copy constructor and assignment operator to allow ownership of the resource to be copied or moved.
That is good C++ practice, but has nothing to do with object-oriented design. Not everything does. OOP isn't the holy grail of programming, and not everything has to be OOP. Good design is much more important than good OOP.