Pointers to pointers in hash Tables - c++

i don't quite understand why the following code does what it does.
void initializeTable()
{
NodeT* (*hashTable) ;
*hashTable=(NodeT*)malloc(30*sizeof(NodeT));
int i;
for(i=0;i<30;i++)
{
(*hashTable)[i].info=(char*)malloc(10*sizeof(char));
strcpy((*hashTable)[i].info,"a");
cout<<(*hashTable)[i].info<<" ";
}
}
I am trying to understand how hash Tables work. In the first version of my program I used something like NodeT* hashTable[arraySize] in order to create an array of pointers to NodeT, in order to do the chaining. After this I decided to try and allocate dinamycally memory for the array, so I tried to use the (I think) equivalent NodeT* (*mockTable).
My question is the following: why do I have to use (*hashTable)[i].info, and not (*hashTable)[i]->info ? As far as i concerned, hashTable is a pointer which points to an array of pointers to NodeT, so this shouldn't happen. What am i getting wrong here?

You got the basic idea but it seem you miscount the pointers
your hashTable is a pointer to pointer (**), and when you access it in the strcpy you actually get into the value of this double pointer the 1'st is with the array index [i] and the second is with the *hashTable which is when accessing a variable calling the Value inside it.
so if you define a duel pointer variable
StrutT **temp;
and you want to access a field inside it
you can
*temp[i].field
but in case you would only want to access at level of a single pointer (same **temp) you would need:
temp[i]->field
or
*temp->field
which both only "pop" the top most pointer

Related

cannot assign to array of pointers in c++

I need to keep an array of pointers in c++. I have a Set which keeps objects of my class. Then I need to iterate over the set and keep the pointer of each item in array. array is 2D by the way. so What I need in summary is :
pointers[1][4] = PinterToAnItem; the reason is I need to delete the item later, So I want to keep the pointer and directly go to that and delete it, instead of iterate again and find and then delete. But I have an error in assigning the array. I dont know how this idea will work, but so far it gives me error. Please let me know if it is not clear
the error is : " a value of type CONST Movie cannot be assigned to type of Movie"
struct Movie
{
int movieId;
int shopId;
int priceId;
};
Movie *pointers[100][100];
set<Movie> setMovie;
void main()
{
//reading and initialize the set with movies
// for example movie1 = {0,10,3} so I want to keep in my array a pointer to this object as:
// pointer [0][10] = ObjectPointer
// I have error in loop body. Also (*id), id and &id does not work.
for (auto id = setMovie.begin(); id != setMovie.end(); id++)
pointers[(*id).movieId][(*id).shopId] = &(*id);
}
2- by the way, do you guys think it is a fine Idea? can I delete pointer[0][10] which points to an object in my set? so by this way I don't need to iterate again through the set and delete (0,10). I have a pointer to (0,10) and I erase it from the set.
Thanks
EDITED
The answer from #Jeffry is right but it does not work for rest of my problem which is erasing the specified item. i intended to keep a pointer to an item and then erase it directly. But we know set.erase(ITERATOR) or (actual_value). so pointer here does not work for me. I had to change array of iterators, then it works. So I completed here maybe works for some later.
set<Movie> ::iterator pointers[100][100];
for (auto id = setMovie.begin(); id != setMovie.end(); id++)
pointers[(*id).movieId][(*id).shopId] = id; // I changed here as well
setMovie[1].erase(pointers[1][0]); // works well
// pointers[1][0] is an iterator to an item in set with movieid=1,shopid=0
pointers[(*id).movieId][(*id).shopId] = &(*id);
tries to store in pointers a pointer to a Movie, pointing into the setMovie.
Now consider what happens, after you do this. What if you did:
pointers[42][43]->priceId = 44;
That would possibly invalidate the set (you could have twice the same Movie). That is why the set doesn't let you do it.
One way around is:
const Movie *pointers[100][100];
Then, you could store the pointer because you wouldn't legally be allowed to modify movies, and mess up the ordering. I'm not sure that makes it a good idea, but it would solve your immediate problem.
For 2, no, it would not be a good idea to call delete on a pointer pointing to a movie stored in your set. You did not call new on this object, so you should not delete it. If you try, you'll get a crash immediately, or much later.

How to delete pointers from vector pointer

I use bison parser generator that has union type for return type productions.
union {
std::vector<std::string*> *vecStrPtr;
// double num; ...
};
how delete pointer from vector pointer;
auto v = new std::vector<std::string*>();
//....
v->push_back(new std::string("text"));
//...
delete v[0];
error: type 'class std::vector<std::__cxx11::basic_string<char>*>' argument given to 'delete', expected pointer delete v[0];
When you do just v[0] you get the vector because v is a pointer and then you need to get value from that vector. You can do it by adding another array access. So working code would look like delete v[0][0];. But two array accesses can be confusing when you are accessing value from one dimension array (vector).
Another way to get vector from pointer v is to dereference it. Code would look like (*v)[0]. It's more clear accessing the value. With (*v) you will get the vector and then the array access is to access the value from vector.
To remove value from vector use method erase. For more information about that method look at this link. Code example would look like:
auto v = new std::vector<std::string*>();
//....
v->push_back(new std::string("text"));
//...
delete (*v)[0];
v->erase(v->begin());
Better is to write code without keyword new. With that rule you will get less memory leaks. It makes your developing easier. But in some cases you can't use it. Your code example modified by that rule would look like:
std::vector<std::string> v;
v.push_back(std::string("text"));
//here is how to get pointers from it
std::string* ptrToElement = &(v[0]);
std::vector<std::string>* ptrToVector = &v;
The right way to free one item is:
delete (*v)[index];
v->erase(b->begin()+index);
However, You should make sure that you really want to allocate a vector in the free store. It seems usually so wrong.
P.S. As #Dahn mentioned, Those two instructions should be atomic.

Select a random object from an array of objects

I'd like to implement a function that selects a random object from an array of objects and returns it to me. It should be something like (in C++ instead of psuedocode):
getRandomObject(objectList) {
return objectList[int(random(length of objectList))];
}
My current code looks like this, but doesn't seem to work:
//definition of random selector
object getRandomObject(Object* objectList) {
return objectList[int(ofRandom(0, sizeof(objectList)))];
};
//create a pointer for the listOfObjects
object* listOfObjects;
//create an empty object to put the randomly selected object in
object randomObject;
//later in the code, populate the array:
object* listOfObjects[] = {
new Object(),
new Object(),
new Object()
};
//select random object
randomObject = getRandomObject(listOfObjects);
But this seems to return a segmentation fault. A few problems I've noticed:
sizeof() returns the size of the pointer in getRandomObject, not the size of the array. is there a good way to get the size of the array? It might involves not using a float* pointer for the array. Is this a good use case for vectors?
I think that much of the problem lies in how I'm creating my arrays, and not so much in how I'm selecting the random object from them. I'm relatively new to C++ (coming from a Java background), so much of pointers / references / memory management in general is new to me.
thanks!
I see one definite problem and one possible one. The definite problem is that sizeof(objectList) returns the size of the objectList pointer, which will be 4 or 8 on most platforms. It does not return the number of elements in the array, objectList. Either pass in the length of the array or use std::vector or std::array.
The second possible problem relates to ofRandom. Make sure that ofRandom(a,b) returns numbers >= a, but strictly < b. If it returns values <= b, then you'll need to us ofRandom(0, objectVector.size() - 1). Typically, functions like this are written to return values strictly < b, but you should check.
C++ has an array template class that you may want to consider using. Check out the documentation here:
http://www.cplusplus.com/reference/array/array/
This type has a method, size(), that will return the length of the array.
When the sizeof operator is applied to an array, it yields the total
number of bytes in that array, not the size of the pointer represented
by the array identifier.
Quote
So you take the space alocated for your whole array and divide by the memory need just for one element: sizeof(objectList) / sizeof(*objectList).
Mr Fooz noticed issues that cause a segfault.
Other compilation issues are:
listOfObjects is declared with 2 different types: object* and object*[3] while getRandomObject expects a type Object*.
listOfObjects[] contains elements of type object* while getRandomObject reads elements of type Object and returns object.

Dynamic array allocation in C++ question

I have a struct of type Duplicate
I have a variable of type int called stringSize, it has a value of 5
I am creating a dynamic array:
Duplicate *duplicates;
duplicates = new Duplicate[stringSize - 1];
Later I delete[] duplicates;
I'm getting one member in that array only? I've verified that stringSize - 1 = 4 with a debug walk through. What can I do to get the 4 members I need?
Any help appreciated,
Thanks // :)
Duplicate *duplicates;
duplicates = new Duplicate[stringSize - 1];
Indeed gives you duplicates[0-3] (Assuming stringSize - 1 is 4, like you say). How are you determining you're getting less?
I suspect you may be doing something like: sizeof(duplicates) / sizeof(duplicates[0]), and on an off-change getting one. The above code only works for statically allocated arrays, where sizeof(duplicates) would match the size of the array, in bytes. In your case, it'll simply return the size of a pointer on your system. (duplicates is a Duplicate*)
And mandatory: Use std::vector if this is "real" code.
Your debugger is doing the best it can. As far is it's concerned, you've merely got a pointer to some data. Consider:
Duplicate foo;
Duplicate *duplicates_A;
duplicates_A = &foo; // points to one Duplicate
Duplicate *duplicates_B;
duplicates_B = new Duplicate[4]; // points to memory containing 4 Duplicate's
bar(duplicates_A);
bar(duplicates_B);
void bar(Duplicate* p)
{
// is p a pointer to one value, or is it an array?
// we can't tell, and this is the same boat your debugger is in
}
How should the debugger, just given a pointer, know if it's pointing to an array or just one value? It cannot, safely. (It would have to determine, somehow, if the pointer was to an array, and the size of that array.)
You can't use sizeof to determine the size of a dynamic array. In fact, there isn't a standard API to determine the size of a dynamic array.
Use std::vector if you need to access the size.
If you use a debugger to view the elements you get, the problem may be that the type of your variable is Duplicate* which is just a pointer (which in C happens to also be an array but the type is just a pointer to one instance of Duplicate.

Why is memory still accessible after std::map::clear() is called?

I am observing strange behaviour of std::map::clear(). This method is supposed to call element's destructor when called, however memory is still accessible after call to clear().
For example:
struct A
{
~A() { x = 0; }
int x;
};
int main( void )
{
std::map< int, A * > my_map;
A *a = new A();
a->x = 5;
my_map.insert( std::make_pair< int, *A >( 0, a ) );
// addresses will be the same, will print 5
std::cout << a << " " << my_map[0] << " " << my_map[0]->x << std::endl;
my_map.clear();
// will be 0
std::cout << a->x << std::endl;
return 0;
}
The question is, why is variable a still accessible after its destructor was called by map::clear()? Do I need to write delete a; after calling my_map.clear() or is it safe to overwrite the contents of a?
Thanks in advance for your help,
sneg
If you store pointers on a map (or a list, or anything like that) YOU are the responsible for deleting the pointers, since the map doesn't know if they have been created with new, or not. The clear function only invokes destructors if you don't use pointers.
Oh, and one more thing: invoking a destructor (or even calling delete) doesn't mean the memory can't be accessed anymore. It only means that you will be accessing garbage if you do.
std::map does not manage the memory pointed to by the pointer values - it's up to you to do it yourself. If you don't want to use smart pointers, you can write a general purpose free & clear function like this:
template <typename M> void FreeClear( M & amap )
for ( typename M::iterator it = amap.begin(); it != amap.end(); ++it ) {
delete it->second;
}
amap.clear();
}
And use it:
std::map< int, A * > my_map;
// populate
FreeClear( my_map )
;
That's because map.clear() calls destructors of the data contained in the map, in your case, of the pointer to a. And this does nothing.
You might want to put some kind of smart pointer in the map for the memory occupied by a to be automatically reclaimed.
BTW, why do you put the template arguments in the call to make_pair? The template argument deduction should do pretty well here.
When you free a piece of heap memory, its contents don't get zeroed. They are merely available for allocation again. Of course you should consider the memory non accessible, because the effects of accessing unallocated memory are undefined.
Actually preventing access to a memory page happens on a lower level, and std libraries don't do that.
When you allocate memory with new, you need to delete it yourself, unless you use a smart pointer.
Any container stores your object Type and call corresponding constructors: internal code each node might look similar to:
__NodePtr
{
*next;
__Ty Val;
}
When you allocate it happens by constructing the val based on type and then linking. Something similar to:
_Ty _Val = _Ty();
_Myhead = _Buynode();
_Construct_n(_Count, _Val);
When you delete it calls corresponding destructors.
When you store references (pointers) it won't call any constructor nor it will destruct.
Having spent the last 2 months eating, sleeping, and breathing maps, I have a recommendation. Let the map allocate it's own data whenever possible. It's a lot cleaner, for exactly the kind of reasons you're highlighting here.
There are also some subtle advantages, like if you're copying data from a file or socket to the map's data, the data storage exists as soon as the node exists because when the map calls malloc() to allocate the node, it allocates memory for both the key and the data. (AKA map[key].first and map[key].second)
This allows you to use the assignment operator instead of memcpy(), and requires 1 less call to malloc() - the one you make.
IC_CDR CDR, *pThisCDRLeafData; // a large struct{}
while(1 == fread(CDR, sizeof(CDR), 1, fp)) {
if(feof(fp)) {
printf("\nfread() failure in %s at line %i", __FILE__, __LINE__);
}
cdrMap[CDR.iGUID] = CDR; // no need for a malloc() and memcpy() here
pThisCDRLeafData = &cdrMap[CDR.iGUID]; // pointer to tree node's data
A few caveats to be aware of are worth pointing out here.
do NOT call malloc() or new in the line of code that adds the tree node as your call to malloc() will return a pointer BEFORE the map's call to malloc() has allocated a place to hold the return from your malloc().
in Debug mode, expect to have similar problems when trying to free() your memory. Both of these seem like compiler problems to me, but at least in MSVC 2012, they exist and are a serious problem.
give some thought as to where to "anchor" your maps. IE: where they are declared. You don't want them going out of scope by mistake. main{} is always safe.
INT _tmain(INT argc, char* argv[]) {
IC_CDR CDR, *pThisCDRLeafData=NULL;
CDR_MAP cdrMap;
CUST_MAP custMap;
KCI_MAP kciMap;
I've had very good luck, and am very happy having a critical map allocate a structure as it's node data, and having that struct "anchor" a map. While anonymous structs have been abandoned by C++ (a horrible, horrible decision that MUST be reversed), maps that are the 1st struct member work just like anonymous structs. Very slick and clean with zero size-effects. Passing a pointer to the leaf-owned struct, or a copy of the struct by value in a function call, both work very nicely. Highly recommended.
you can trap the return values for .insert to determine if it found an existing node on that key, or created a new one. (see #12 for code) Using the subscript notation doesn't allow this. It might be better to settle on .insert and stick with it, especially because the [] notation doesn't work with multimaps. (it would make no sense to do so, as there isn't "a" key, but a series of keys with the same values in a multimap)
you can, and should, also trap returns for .erase and .empty() (YES, it's annoying that some of these things are functions, and need the () and some, like .erase, don't)
you can get both the key value and the data value for any map node using .first and .second, which all maps, by convention, use to return the key and data respectively
save yourself a HUGE amount of confusion and typing, and use typedefs for your maps, like so.
typedef map<ULLNG, IC_CDR> CDR_MAP;
typedef map<ULLNG, pIC_CDR> CALL_MAP;
typedef struct {
CALL_MAP callMap;
ULNG Knt;
DBL BurnRateSec;
DBL DeciCents;
ULLNG tThen;
DBL OldKCIKey;
} CUST_SUM, *pCUST_SUM;
typedef map<ULNG,CUST_SUM> CUST_MAP, CUST_MAP;
typedef map<DBL,pCUST_SUM> KCI_MAP;
pass references to maps using the typedef and & operator as in
ULNG DestroyCustomer_callMap(CUST_SUM Summary, CDR_MAP& cdrMap, KCI_MAP& kciMap)
use the "auto" variable type for iterators. The compiler will figure out from the type specified in the rest of the for() loop body what kind of map typedef to use. It's so clean it's almost magic!
for(auto itr = Summary.callMap.begin(); itr!= Summary.callMap.end(); ++itr) {
define some manifest constants to make the return from .erase and .empty() more meaningfull.
if(ERASE_SUCCESSFUL == cdrMap.erase (itr->second->iGUID)) {
given that "smart pointers" are really just keeping a reference count, remember you can always keep your own reference count, an probably in a cleaner, and more obvious way. Combining this with #5 and #10 above, you can write some nice clean code like this.
#define Pear(x,y) std::make_pair(x,y) // some macro magic
auto res = pSumStruct->callMap.insert(Pear(pCDR->iGUID,pCDR));
if ( ! res.second ) {
pCDR->RefKnt=2;
} else {
pCDR->RefKnt=1;
pSumStruct->Knt += 1;
}
using a pointer to hang onto a map node which allocates everything for itself, IE: no user pointers pointing to user malloc()ed objects, works well, is potentially more efficient, and and be used to mutate a node's data without side-effects in my experience.
on the same theme, such a pointer can be used very effectively to preserve the state of a node, as in pThisCDRLeafData above. Passing this to a function that mutates/changes that particular node's data is cleaner than passing a reference to the map and the key needed to get back to the node pThisCDRLeafData is pointing to.
iterators are not magic. They are expensive and slow, as you are navigating the map to get values. For a map holding a million values, you can read a node based on a key at about 20 million per second. With iterators it's probably ~ 1000 times as slow.
I think that about covers it for now. Will update if any of this changes or there's additional insights to share. I am especially enjoying using the STL with C code. IE: not a class in sight anywhere. They just don't make sense in the context I'm working in, and it's not an issue. Good luck.