Good Object Oriented Design When Deleting, C++ - c++

The code below deletes the symbol associated with the stock object just fine. Its just bad object oriented design.
The way that i am searching for each stock symbol is by using a != or == test for NULL.
bool hashmap::remove(char const * const symbol, stock &s,
int& symbolHash, int& hashIndex, int& usedIndex)
{
if ( isAdded == 0 ) return false;
if ( hashTable[isRemoved].symbol == symbol ) return true;
else
{
symbolHash = this->hashStr( symbol );
hashIndex = symbolHash % maxSize;
usedIndex = hashIndex;
}
for ( int integer = 0; integer < maxSize; integer++ )
{
if ( hashTable[usedIndex].symbol != NULL &&
strcmp( hashTable[usedIndex].symbol, symbol ) == 0 )
{
isAdded--;
isRemoved = hashIndex;
s = &hashTable[usedIndex];
delete hashTable[usedIndex].symbol;
hashTable[usedIndex].symbol = NULL;
return true;
}
++usedIndex %= maxSize; // wrap around if needed
}
return false;
}
Im wondering now, if i delete in a such a way that:
hashTable[usedIndex].symbol = hashTable[NULL].symbol
Thereby, changing the way I logically test for an empty or found stock symbol. Is their a way to remove my stock symbol without having to redo the aspect of finding and searching?
Is this the correct way to remove in object oriented design?

First of all, "object oriented design" is very ambiguous.
Is isAdded a member variable? It isn't clear that it is and creates another dependency on this function that isn't obvious when looking at the signature. Same thing goes for isRemoved.
Generally, a function that takes 5 arguments is getting close to showing that there is too much dependencies on this function (nevermind the invisible dependencies in isAdded, isRemoved, and hashTable).
I'm not sure what type hashTable is, but you should never have to call delete in 2009. You can use auto_ptr, shared_ptr, unique_ptr (in C++0x). These will take care of freeing your resource when it is not needed anymore. If you are using an STL container, then don't use auto_ptr though.
If you would like to use a hashtable in C++, you really should consider using a hash_map. That will be a much better implementation than 99.9999% of us can accomplish.
When using a hash_map, you can call void erase(iterator first, iterator last) to erase/delete an element.

How is an insert collision handled? Most standard solutions—such as a linear search for an open slot, or generating a new hash—make deleting an element problematic. If deletions are common, consider using a list structure instead.

Related

C++ int& operator[](string key) function using Linked List

For a comsci project I have been assigned recently, we have to implement our own version of the STL Map using a Linked List. In our operator[] overload function though we cannot figure out how to access and return the "int&".
This is what we have tried doing so far:
int& LLMap::operator[](string key){
//return this->myMap.searchforNodeAddress(key)->getPairValue();
return this->myMap.searchforNodeAddress(key)->getPairValueAddress();
}
And here are the implementations of the functions being called:
PairNode* PairLinkedList::searchforNodeAddress(string desiredKey){
PairNode* currNode = this->getPairHead();
while (currNode != NULL){
if (currNode->getPairKey() == desiredKey){
return currNode;
}
else{
currNode = currNode->getNext();
}
}
}
And
int PairNode::getPairValue(){
return this->value;
}
int* PairNode::getPairValueAddress(){
return &(this->value);
}
We have been trying to figure this out for quite some time now and are completely stumped, any pointers in the right direction or any assistance at all would be greatly appreciated. Thank you
You can either dereference the address...
return *myMap.searchforNodeAddress(key)->getPairValueAddress();
...or change getPairValue()...
int& PairNode::getPairValue() // now returns int&
Separately, the STL map (lowercase "m") is confined to history - you probably mean the C++ Standard Library std::map, and you can't strictly "implement" either with a linked list: they're necessarily balanced binary trees, given the Standard's performance guarantees. You can implement something with a std::map-like interface - minus those performance characteristics - over a linked list....
Also, prefer to pass string parameters that won't be modified inside a function using const std::string&: it avoids allocating extra memory and copying the text over, only to release it after the function exits.

Is this a valid way of removing items from of std::vector?

Here's my code for updating a list of items in a vector and removing some of them:
std::vector<Particle*> particles;
...
int i = 0;
while ( i < particles.size() ) {
bool shouldRemove = particles[ i ]->update();
if ( shouldRemove ) {
delete particles[ i ];
particles[ i ] = particles.back();
particles.pop_back();
} else {
i++;
}
}
When I find an item that should be removed, I replace it with the last item from the vector to avoid potentially copying the rest of the backing array multiple times. Yes, I know it is premature optimization...
Is this a valid way of removing items from the vector? I get some occasional (!) crashes somewhere around this area but can't track them down precisely (LLDB fails to show me the line), so I would like to make sure this part is OK. Or is it... ?
UPDATE: I found the bug and indeed it was in another part of my code.
Yes, this is a valid way. But if it is not a performance bottleneck in your program then it's better to use smart pointers to manage the lifetime of Particle objects.
Take a look at std::remove_if.
Also, might be good to use a shared pointer as it may make life easier :-)
typedef std::shared_ptr< Particle > ParticlePtr;
auto newend = std::remove_if( particles.begin(), particles.end(), [](ParticlePtr p) {return p->update();} );
particles.erase( newend, particles.end() );
You are iterating over an STL vector, so use iterators, it's what they're for.
std::vector<Particle*>::iterator particle = particles.begin();
while ( particle != particles.end() ) {
bool shouldRemove = particle->update();
if ( shouldRemove ) {
particle = particles.remove(particle); //remove returns the new next particle
} else {
++particle;
}
}
Or, even better, use smart pointers and the erase/remove idiom. Remove_if itself does as you describe, moving old members to the back of the vector and returning an iterator pointing to the first non-valid member. Passing this and the vector's end() to erase allows erase to erase all the old members as they are in a contiguous block. In your scenario, you would have to delete each before calling erase:
auto deleteBegin = std::remove_if(
particles.begin(), particles.end(),
[](Particle* part){ return part->update();}));
for(auto deleteIt = deleteBegin; deleteIt != particles.end(); ++deleteIt)
delete *deleteIt;
std::erase(deleteBegin, particles.end());
Or pre C++11:
bool ShouldDelete(Particle* part) {
return part->update();
}
typedef vector<Particle*> ParticlesPtrVec;
ParticlesPtrVec::iterator deleteBegin = std::remove_if(
particles.begin(), particles.end(), ShouldDelete);
for(ParticlesPtrVec::iterator deleteIt = deleteBegin;
deleteIt != particles.end(); ++deleteIt)
delete *deleteIt;
std::erase(deleteBegin, particles.end());
Then test the whole code for performance and optimise wherever the actual bottlenecks are.
I don't see any direct issue in the code. You are probably having some issues with the actual pointers inside the vector.
Try running valgrind on your code to detect any hidden memory access problems, or switch to smart pointers.

how to convert iterator of list STL to instance (C++)

this is my first time using the list STL and i'm not sure if what i'm trying to do is possible.
I have class_B which holds a list of class_A, I need a function in class_B that takes an ID, searches the list for an instance with the same ID, and gets a pointer form the list to the instance in that list:
bool class_B::get_pointer(int ID,class_A* pointer2A){
list<class_A>::iterator i;
for(i=class_A.begin();i!=class_A.end();i++){
if((*i).get_id()==ID) {
\\pointer2A=(i);<---------------this is what I'm trying to do
return true;
}
}
pointer2A=NULL;
return false;
}
how do I perform this, is it possible to convert from iterator to instance ?
EDIT:
I'm using this function in a multi-threaded program and I can't return an iterator to the calling function since another thread might delete an element of the list.
Now that I have a pointer to my element(and lets say it's locked so it can't be deleted), and a different thread removed another element and performed a sort on the list, what will happen to the pointer I'm holding ? (I don't know how the list rearranges the elements, is done by copying the elements using a copy c'tor, or by another mean?).
Useless answer was the most helpful in my case (BIG thanks), and yes I should use a reference to the pointer since I'm planing to change it.
You should write this:
pointer2A= &*i;
Here *i returns the object whose address you can get by prepending & as : &*i.
Note that i is not same as &*i. See this topic for more general discussion:
Difference between &(*similarObject) and similarObject? Are they not same?
Anyway, I would suggest you to read the pointer itself as:
class_A* class_B::get_pointer(int ID)
{
//I assume the name of the list is objA, not class_A
for(list<class_A>::iterator i=objA.begin();i!=objA.end();i++)
{
if( i->get_id()==ID)
{
return &*i;
}
}
return NULL; //or nullptr in C++11
}
Or, in C++11, you can use std::find_if as:
auto it = std::find_if(objA.begin(),
objA.end(),
[&](class_A const &a){ return a->get_id() == ID;});
classA *ptr = NULL;
if ( it != objA.end())
ptr = &*it; //get the pointer from iterator
Make sure get_id is a const member function.
if(i->get_id()==ID) {
pointer2A=&*i;
return true;
}
iterators are designed to have similar semantics to pointers, so for example you can write i->get_id() just as if you had a pointer to A.
Similarly, *i yields a reference A&, and &*i converts that back into a pointer - it looks a bit clunky (it would be an identity operation if i were really a pointer), but it's idiomatic.
Note that this won't do what you presumably want anyway - the caller's class_A* pointer2A is passed by value, so only get_pointer's copy of the pointer is modified, and the caller won't see that value. Try this:
bool class_B::get_pointer(int ID, class_A *& pointer2A)
{
list<class_A>::iterator i;
for(i=class_A.begin();i!=class_A.end();i++) {
if(i->get_id()==ID) {
pointer2A=&*i;
return true;
}
}
pointer2A=NULL;
return false;
}
Now pointer2A is passed by reference, so the caller's copy gets modified inside your function.
BTW, you can read the parameter declaration class_A * & pointer2A right-to-left, as "pointer2A is a reference to a pointer to class_A".
If you have an iterator, you can get a raw pointer by simply dereferencing the iterator (which gives you a reference), and then taking the address of that (which gives you a pointer). So, in your case:
pointer2A = &*i;
This might seem like an odd, clumsy way to get a pointer, and it is. But you normally don't care about pointers when you are using the collections & iterators from the Std Lib. Iterators are the glue that hold the "STL" together. That's what you should be dealing with, by and large, rather than raw pointers.
The loop you've written above certainly gets the job done that you wish to accomplish, but there are better* ways to accomplish the same goal. (Better is a subjective term.) In particular, the <algorithm> library provides both std::find and std::find_if which do just what they say they do. They find something in a collection. find will find something that is equal to what you're looking for. find_if will find something that matches some criteria that you specify. The latter is the appropriate algorithm to use here, and there are two main ways to use it.
The first, more "traditional" approach is to use a functor:
struct match_id : public std::unary_function<bool, class_A>
{
match_id(int ID) : id_(id) {};
bool operator()(const class_A* rhs) const
{
if( id_ == rhs->get_id() )
return true;
else
return true;
};
/* ... */
list<class_A>::iterator it = std::find_if(objA.begin(), objA.end(), match_id(ID));
This approach works in C++03 or C++11. Some people don't like it because it is rather verbose. I like it, on the other hand, because the actual buisness logic (the find_if call) is quite succinct and more expressive than an explicit loop.
In C++11, you can use a lambda in place of the functor:
unsigned ID = 42;
std::find_if( objA.begin(), objB.end(), [&ID](const class_A& rhs) -> bool { return rhs.get_id() == ID; } };
There's a tradeoff here. On the pro side, you don't have to write 10 or so lines of code for the functor, but on the con side, the lambda syntax is funky and takes a bit of getting used to.

Safe Delete in C++

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.

std::map inizialitazion (only one time)

I have a function that translates data using std::map
struct HistoParameter
{
int nbins;
float first;
float last;
HistoParameter(int _nbins, int _first, int _last) :
nbins(_nbins), first(_first), last(_last) {};
};
HistoParameter* variable_to_parameter(char* var_name)
{
std::map<const std::string, HistoParameter*> hp;
hp[std::string("ph_pt")] = new HistoParameter(100,0,22000);
hp[std::string("ph_eta")] = new HistoParameter(100,-3,3);
// ...
return hp[var_name];
}
My struct is very light, but image it can be heavy. The prolem is that every time I call this function it create a lot of HistoParameter objects, maybe a switch case is more efficient. First question: I'm creating garbage?
Second solution:
bool first_time = true;
HistoParameter* variable_to_parameter(char* var_name)
{
static std::map<const std::string, HistoParameter*> hp;
if (first_time)
{
hp[std::string("ph_pt")] = new HistoParameter(100,0,22000);
hp[std::string("ph_eta")] = new HistoParameter(100,-3,3);
// ...
}
first_time = false;
return hp[var_name];
is it ok? Better solution?
The second solution seems OK to me - you can say:
if ( hp.empty() ) {
// populate map
}
I would also consider making it a map of values rather than pointers - I don't see you need dynamic allocation here:
std::map <std::string, HistoParameter> hp;
then:
hp["ph_pt"] = HistoParameter(100,0,22000);
Note you don't need the explicit std::string conversion. Or better still:
hp.insert( std::make_pair( "ph_pt", HistoParameter(100,0,22000 )));
The first solution produces a lot of garbage. Why don't you return the class by value? It's quite lightweight, and you wouln't have to dynamically allocate it.
HistoParameter variable_to_parameter(char* var_name)
{
static std::map<const std::string, HistoParameter> hp;
if ( hp.empty() )
{
hp.insert( std::make_pair( "ph_pt", HistoParameter(100,0,22000) ) );
hp.insert( std::make_pair( "ph_eta", HistoParameter(100,-3,3) ) );
//...
}
return hp[var_name];
}
If the class returned gets larger, and you want a power-tool, then try out boost::flyweight.
If you don't want to pass back a big structure, you can do:
HistoParameter& variable_to_parameter(char* var_name)
{
// same code
}
... and even throw in a const if you want it immutable.
Edit: added make_pair, as suggested by Niel.
Your second solution should certainly improve efficiency, but isn't (at least IMO) the best implementation possible. First of all, it makes first_time publicly visible, even though only variable_to_parameter actually cares about it. You've already made hp a static variable in the function, and first_time should be as well.
Second, I would not use pointers and/or dynamic allocation for the HistoParameter values. At one int and two floats, there's simply no reason to do so. If you're really passing them around so much that copying became a problem, you'd probably be better off using some sort of smart pointer class instead of a raw pointer -- the latter is more difficult to use and much more difficult to make exception safe.
Third, I'd consider whether it's worthwhile to make variable_to_parameter into a functor instead of a function. In this case, you'd initialize the map in the ctor, so you wouldn't have to check whether it was initialized every time operator() was invoked. You can also combine the two, by have a static map in the functor. The ctor initializes it if it doesn't exist, and operator() just does a lookup.
Finally, I'd note that map::operator[] is primarily useful for inserting items -- it creates an item with the specified key if it doesn't exist, but when you're looking for an item, you usually don't want to create an item. For this, you're generally better off using map.find() instead.
I'd have a std::map< std::string, HistoParameter *> member and do
InitializeHistoParameter()
{
myMap["ph_pt"] = new ...
myMap["ph_eta"] = new ...
}
And then
HistoParameter* variable_to_parameter(char* var_name)
{
return myMap[var_name];
}
either way, you are creating memory leak.
each time the = operator is called, for example:
hp[std::string("ph_pt")] = new HistoParameter(100,0,22000);
you are creating a new HistoParameter object and pairing the key "ph" with this most recent object, leaving the previous one dangling.
If creating a new object each time is your actual intent, you probably need to call
delete hp[std::string("ph_pt")];
before the new operation.
My suggestion is to avoid raw new operations as much as possible and resort to smart pointers such as boost::share_ptr for object life time management.