Once the object is copied to the vector the pointer isn't updated.
If I use a copy constructor to fix this problem I get awkward results.
Could anyone please help me find a solution? Thanks in advance.

#include <iostream>
#include <vector>
using namespace std;

typedef struct {

	void *map;

} XE_MAP;

typedef struct MAP_LAYER {

	MAP_LAYER() 
	{				
		map = (XE_MAP*)malloc(sizeof(XE_MAP));
		map->map = (void*)data;

		cout << "Data is at " << &data << " and map->map points at " << map->map << endl;
		
	}

	unsigned short data[2500];
	XE_MAP* map;	
	
};

int main (int argc, char * const argv[]) {
	
	vector<MAP_LAYER> Map; 
        MAP_LAYER layer;
	
	Map.push_back(layer);

	cout << "Data is at " << &Map[0].data << " and map->map points at " << Map[0].map->map << endl;

		
    return 0;
}

Output

Data is at 0xbf5dc008 and map->map points at 0xbf5dc008
Data is at 0x8052568 and map->map points at 0xbf5dc008

Recommended Answers

All 6 Replies

Do you simply want a separate pointer for the data? If so then this might work--

#include <iostream>
#include <vector>
using namespace std;

typedef struct {

	void *map;

} XE_MAP;

typedef struct MAP_LAYER {

	MAP_LAYER()
	{
		map = (XE_MAP*)malloc(sizeof(XE_MAP));
		map->map = (void*)data;

		cout << "Data is at " << &data << " and map->map points at " << map->map << endl;

	}
	MAP_LAYER(const MAP_LAYER& other){

        XE_MAP *temp = (XE_MAP*)malloc(sizeof(XE_MAP));
        *temp = *other.map; // probably not good - simply copying actual object at location
        map = temp;
        unsigned short temp2[RANGE];
        for(int i = 0; i < RANGE; i++)temp2[i] = other.data[i];

        map->map = (void*)temp2;
        cout << "copy constructor invoked" << endl;
	}

    enum SIZE {RANGE = 2000};
	unsigned short data[RANGE];
	XE_MAP* map;

};

int main (int argc, char * const argv[]) {

	vector<MAP_LAYER> Map;
        MAP_LAYER layer;

	Map.push_back(layer);
	cout << "Data is at " << &Map[0].data << " and map->map points at " << Map[0].map->map << endl;
    return 0;
}

--I'm sure someone knows a better way of doing this with a copy function, but I don't know much about copy functions yet.

A few comments

- When handling dynamically allocated memory in C++, you should use the new operator. Malloc is bad, since all it does is allocate memory on the heap - if you're creating an object of a particular class/struct, then that object will be uninitialised.

- Keep in mind the rule of three, which states that if your class needs either a Copy Constructor, a Destructor, or an overloaded assignment operator, then it generally needs all 3.


In reply to Alex Edwards - What exactly do you intend the copy constructor in your example to do? at the moment the program displays undefined behaviour where you have a dangling pointer to an array which will be deallocated as soon as the object has been created. The result is neither a deep nor shallow copy of the original object, but just an object in an invalid state.


To the OP - perhaps you could explain exactly what it is you're trying to do here since void pointers are generally unsafe (You need to know exactly what you're doing in order for them to be meaningful); The initial example you provided is displaying that output because your object is being directly copied value-for-value (A shallow copy). Which means your array is copied as you'd expect, and the pointer member is also having its value copied.
If you posted the copy constructor which you tried, someone may be able to point out where you went wrong. It seems that you require a deep copy to be made.

commented: Thanks for pointing that out! +3
commented: and happy belaaaaa..aated b-day :D +5

In reply to Alex Edwards - What exactly do you intend the copy constructor in your example to do? at the moment the program displays undefined behaviour where you have a dangling pointer to an array which will be deallocated as soon as the object has been created. The result is neither a deep nor shallow copy of the original object, but just an object in an invalid state.

Whoops, I completely forgot to assign the newly generated array to the data before setting the struct's void pointer... I was tired last night, forgive me.

You're right, the newly generated array at the moment will just cause unnecessary overhead as it will fall out of scope after the object is created, leaving the map->map pointer pointing to nothing.

Here's the correction--

#include <iostream>
#include <vector>
using namespace std;

typedef struct {

	void *map;

} XE_MAP;

typedef struct MAP_LAYER {

	MAP_LAYER()
	{
		map = (XE_MAP*)malloc(sizeof(XE_MAP));
		map->map = (void*)data;

		cout << "Data is at " << &data << " and map->map points at " << map->map << endl;

	}
	MAP_LAYER(const MAP_LAYER& other){

        XE_MAP *temp = (XE_MAP*)malloc(sizeof(XE_MAP));
        *temp = *other.map; // probably not good - simply copying actual object at location
        map = temp;
    
        for(int i = 0; i < RANGE; i++)data[i] = other.data[i];
        map->map = (void*)data; // correction

        cout << "copy constructor invoked" << endl;
	}

    enum SIZE {RANGE = 2000};
	unsigned short data[RANGE];
	XE_MAP* map;

};

int main (int argc, char * const argv[]) {

	vector<MAP_LAYER> Map;
        MAP_LAYER layer;

	Map.push_back(layer);
	cout << "Data is at " << &Map[0].data << " and map->map points at " << Map[0].map->map << endl;
    return 0;
}

--This is assuming a copy of all of the elements of data in the previous object are needed. Again, I know there are better ways of doing it but this is a straightforward approach.

This code is an example of a fantastical C and C++ himera.
If it's C, why constructors?
If it's C++, why typedefs?

Some notes. Let's start from trifles.

1. Try to follow common conventions. You are free in names choice (all but keywords) but as usually all-capitals are reserved for macros (in the last resort for constants). Class (and struct) names are nouns with 1st capital letter.

2. C++ style for struct declaration is the same as for class declarations:

struct XEmap
{
    void* map;
    // I prefer pmap or what else but not map.
    // It's not a map, it's a pointer to ... map?
    // Feel the difference...
};
// ... and now;
XEmap m1, m2; // and so on...

3. Never use malloc/free in C++ codes, use only new/delete operators: malloc() never calls class or struct constructors, free() never calls destructors. Don't free() pointers obtained from new, don't delete pointers obtained from malloc(). Better forget malloc if you write a program in C++.

Let's come back to XEmap (and others) declaration.

4. We can see XEmap "wrapper" for generic pointers. It's not a real wrapper because of the struct has only public members and no other members (methods). Actually it's the same type as a simple void* type. Why? Is it a proxy for dynamically allocated memory chunk? If so, where is its size (member)? Where is constructor(s) and destructor? Obviously, no useful operations for XEmap struct (except a very dangerous default assignment pointer to pointer). XEmap is absolutely useless (and potentially dangerous) artifact.

5. Now struct MAP_LAYER emerged from behind the syntax (and pragmatics) clouds. All public members again but the structure has copy constructor (and no assignment operator - alarm bell rings). MAP_LAYER constructor allocates (via C allocation - see points above) a memory chunk for one pointer. OK (sorry: it's a pity;)), but where is MAP_LAYER destructor to free this allocation? No destructor, no assignment operator. There is a cumbersom, intricate copy constructor. So you have guarantee of memory leaks and other troubles...

It's enough. Please, avoid such incomprehensible, cumbersome and unrealistic examples when you learn a new programming language. It's a wrong way...

Thanks for the replies! I know that the code is missing many important elements since I tried to include the "least" amount of code needed to present my problem. The program is supposed to work with a library written in C.

Well I seem to have found a solution to my problem. Here's the code if anyone wants to take a look at it. Thanks for your help Alex Edwards and everyone else!

#include <iostream>
#include <vector>
using namespace std;

typedef struct {

	void *map;
} xeMap;

xeMap * xeCreateMap(void * data) {
	
	xeMap * map;
	map = (xeMap*)malloc(sizeof(xeMap));
	map->map = (void*)data;
	return map;
}

typedef struct xeMapLayer {

	xeMapLayer() {
				
		map = xeCreateMap(data); 			
		cout << "Data is at " << &data << " and map->map points at " << map->map << endl;	
	} 
	~xeMapLayer() { free(map); }

	unsigned short data[2500];
	xeMap* map;		
};

int main (int argc, char * const argv[]) {
	
	vector<xeMapLayer*> Map;
	xeMapLayer * layer;
	
	layer = new xeMapLayer[3];

	for( int i = 0; i < 3; ++i )
		Map.push_back(&layer[i]);
	
	cout << endl;
	
	for( int i = 0; i < (int)Map.size(); ++i )
		cout << "Data is at " << &Map[i]->data << " and map->map points at " << Map[i]->map->map << endl;
	
	cin.get();	
	delete []layer;
	
    return 0;
}

Output

Data is at 0x805243c and map->map points at 0x805243c
Data is at 0x8052508 and map->map points at 0x8052508
Data is at 0x80525d4 and map->map points at 0x80525d4

Data is at 0x805243c and map->map points at 0x805243c
Data is at 0x8052508 and map->map points at 0x8052508
Data is at 0x80525d4 and map->map points at 0x80525d4
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.