Copying local object to vector - c++

I have a singleton class that holds a vector with data. My problem is that I want to add data to that vector using the standard push_back() method. I have an object I want to save in that vector but it's a local object (created in a method in another class). Obviously, at the end of this method the local variable would be deleted which is fine because I do a push_back() of that data to the vector.
Now, this works fine for as long the method didn't end. After it ends the data is gone. This seems weird because push_back() should be using the copy constructor right? Now, I tried to add the local variable to the vector by reference, by value, as a pointer and with the move constructor in C++11 but all those things don't seem to work.
So this is the setup of the problem class-wise:
ConnectionManager (holds the vector)
ClassA (which has a method with the local typeX object)
So, in short, I want the object created in a method in ClassA to be available after that method but in the vector from the ConnectionManager class.
EDIT: Here's the typeX I'm talking about:
struct Connection
{
SOCKET socket;
PlayerData* pPlayerData;
};
socket is just your normal winsock SOCKET variable and PlayerData* is a custom object created with Google's ProtocolBuffer.
FURTHER EDIT:
This is how I create the data:
Predefined::Connection connTemp;
connTemp.socket = 0;
connTemp.pPlayerData = data;
MultiplayerData::GetInstance()->AddPlayerToGame(connTemp);
connTemp.pPlayerData is, to answer the question, a locally created variable but it's created as a pointer.

If the issue is that you're creating the PlayerData data, and expecting to have the same data be still available after the function exits, it looks like you should use a type such as std::shared_ptr<PlayerData> instead of a naked PlayerData*.
#include <vector>
#include <memory>
//..
class PlayerData
{
int x, y, z;
public:
PlayerData(int a1, int a2, int a3) : x(a1), y(a2), z(a3) {}
};
typedef std::shared_ptr<PlayerData> PlayerDataPtr;
struct Connection
{
SOCKET socket;
PlayerDataPtr pPlayerData;
};
typedef std::vector<Connection> ConnectionVector;
void foo()
{
auto data = std::make_shared<PlayerData>(1, 2, 3); // create data dynamically
//...
Connection connTemp;
connTemp.socket = 0;
connTemp.pPlayerData = data;
MultiplayerData::GetInstance()->AddPlayerToGame(connTemp); // this does the push_back
//...
}
Since pPlayerData is now a shared_ptr, those copies that vector will generate just bump up a reference count, and conversely, when those copies are destroyed, the reference count is decremented. When the reference count reaches 0, then the data will indeed be deleted.
If you haven't called reset on the shared pointer, this is more or less, your guarantee that the data you created before the push_back was done will exist, as long as that entry in the vector wasn't removed.
Also, I edited the example to show a simpler PlayerData class. Note how make_shared is used.

Struct Connection will indeed be copied into the vector, so you don't need to worry about end of its lifetime. pPlayerData however needs to point into a memory allocated with new and owned by somebody.
connTemp.pPlayerData = data;
Where does the 'data' come from - generated locally?
The 'data' needs to be allocated by 'new' at some point.
If the "data" are all unique, consider using auto_ptr or unique_ptr for the type of pPlayerData member - C++ doesn't automatically manage standard pointers. If they're not unique, use shared_ptr or intrusive_ptr - can start with shared and retrofit intrusive later.

Related

C++ add local variables to static vector without copying

im trying to archieve the following in c++:
I want to be able to create local variables, add them to a global static vector and only pointers to them should be added to the vector.
In C# i was able to write (example):
public static List<Component> CACHE = new List<Component>(); //Somewere in class
//Now in method:
Component a = new Component();
a.Name = "Noël";
CACHE.Add(a); //Adds reference to CACHE a without copy
in c++ i see 2 solutions:
1.Use dynamic allocations:
static std::vector<Component*> CACHE; //Somewere in class
//Now in method:
Component* a = new Component();
a->Name = L"Noël";
CACHE.push_back(a);
the problem is that i dont want to use dynamic allocation because its slow.
2.My idea:
(Somehow i have to make the new operator private or just say in the documentation never use new on Component)
//somewere hidden:
std::vector<Component*> GLOBAL_CACHE;
//In method dont use new, instead we use a custom global function
Component* a = CREATE_COMPONENT();
static std::vector<Component*> CACHE; //Example
Component& ExampleRef;//Example
a->Name = L"Noël";
CACHE.push_back(a);
ExampleRef = *a;
and now CREATE_COMPONENT():
Component* CREATE_COMPONENT()
{
GLOBAL_CACHE.push_back(Component()); //Add empty component
return &GLOBAL_CACHE[GLOBAL_CACHE.size() - 1]; //return pointer to construct added above. I think we now have everything on the stack and we just send around pointers to the stack object
}
Is my idea worth it or even working? Or should i just use dynamic allocation?
Doing the same in C++ is not possible because of garbage collection. But you can do it similarly by using shared_ptr<Component> as the element type of your vector:
#include <memory>
std::vector<std::shared_ptr<Component>> CACHE;
// ...
auto a = std::make_shared<Component>();
a->Name = "Noël";
CACHE.push_back(a);
The Component will be automatically destroyed when there's no more references to it.
If you don't intend to store copies of the pointers somewhere else, but CACHE is the only place where you put them, then you can use unique_ptr instead:
#include <memory>
std::vector<std::unique_ptr<Component>> CACHE;
// ...
CACHE.push_back(std::make_unique<Component>());
CACHE.back()->Name = "Noël";
Unlike shared_ptr, unique_ptr can not be copied, only moved, meaning there can only ever be 1 reference to it. The Component object will be automatically destroyed when the unique_ptr is destroyed.
This is using memory allocation, but the same it true for C#.
Note that, unlike C#, using new and delete in C++ is a bad idea because they're prone to resource and memory leaks. Use shared_ptr and unique_ptr instead if you want to create objects on the heap.
Finally, you should read up on "C++ move semantics". You don't need to avoid putting things on the stack. You can move objects instead of copy them. Example:
#include <memory>
std::vector<Component> CACHE;
// ...
Component a;
a.Name = "Noël";
CACHE.push_back(std::move(a)); // No copy. The 'a' variable can no longer be used.
Moves are sometimes automatic and they are a big part of C++. But you need to educate yourself about it.

Remember the original object which is merely able to manage shared memory

I have a question about good C++ style:
I would like to write a class "MyClass" which has one or some pointers as members and MyClass is able to allocate memory to this pointers. I would like to use the implicit give default-copy-constructor (as well as the default-assignement-operator) to copy an instance of MyClass, so that only the pointers were copied and the new object share the data which the initial object has allocated.
My idea was to prohibit copied objects (created with copy constructor or assignment operator) to release memory (as well as allocate memory to member pointers). In order to distinguesh between copied objects and original objects (created by the constructor), I want to use the following code:
class MyClass
{
public:
MyClass(): originalPtr(this) { data = new char[100000]; }
~MyClass() { if(originalPtr == this) delete[] data; }
private:
MyClass *originalPtr;
char *data; // shared data (not copiable)
char otherFeatures[10]; // individual data (copiable)
};
Would this solution (using the comparison with the this-pointer) a good style for such a purpose (e.g. parsing an object by call by value) or is it risky? Of course, I assume that the original object live always longer than the copied objects.
Thank you!
No, this is a bad idea. If the pointers are shared by several instances, than the one to deallocate should be the last one to die, not the original one. This differs in the sense that the original one might not be the one to die, which would cause all others to be pointing at garbage. Even though you assume that it's the last one to die, you need to realise that the inner workings of a class should not rely on external assumptions. That is, the class has no guarantees on how its life span is managed by the rest of the implementation, so it shouldn't make assumptions.
In this situation you should track references to your data. The basic idea is to keep track of how many copies of the class you have. As soon as that count reaches zero, you are free to release that memory; the last copy has just died. Fortunately for you, STL already provides such an implementation. These are known as Smart Pointers. There are others, such as std::unique_ptr, which makes the opposite by ensuring that the data is owned only by a single instance.
Ok, assuming the general case, where the original object does not die at last. I like the idea to just count the instances. For example one could use such a concept:
class MyClass
{
public:
MyClass(): countOfInstances(new int())
{
++*countOfInstances;
data = new char[100000];
}
~MyClass()
{
--*countOfInstances;
if(!countOfInstances)
{
delete[] data;
delete countOfInstances;
}
}
MyClass(const MyClass &other) // analogous for the assignment operator
{
countOfInstances = other.countOfInstances;
data = other.data;
otherFeatures = other.otherFeatures;
++*countOfInstances;
}
private:
int *countOfInstances;
char *data; // shared data (not copiable)
char otherFeatures; // individual data (copiable)
};
Here, one should also make sure that the shared memory is completely allocated before allowing to make copies.

C++ Copy data pointed at by pointer

I'm a long-time reader, and first-time poster... I've searched long and hard to find an answer to something that's really boggling my mind right now. I must be missing something, as I believe this should work...
I'm trying to create a datatable class that will contain it's own copies of the objects passed to it. I've decided to use std::map's to contain this data. See the example code below:
typedef std::map <std::string, myVar *> myVarContainer;
class myObj
{
public:
myObj(void);
virtual ~myObj(void);
void setVar(std::string Key, myVar & Var);
myVar * getVar(std::string Key);
void release()
{
for (myVarContainer::iterator i = VarContainer->begin(); i != VarContainer->end(); ++i)
{
delete (i->second);
}
VarContainer->clear();
};
myVarContainer * VarContainer;
};
typedef std::map <myVar, myObj *> myRow;
class myTable
{
public:
myTable(void);
virtual ~myTable(void);
void addDataPoint(myVar RowID, myVar ColID, myObj * Data)
{
std::map <myVar, myRow *>::iterator i = m_Rows->find(RowID);
if (i == m_Rows->end())
{
m_Rows->insert(make_pair(RowID, new myRow()));
}
i = m_Rows->find(RowID);
// i thought the below line would be creating a copy of the data?
// I thought this logic went:
// 1. create a new object copied from the value of 'Data'
// 2. return a pointer to this object and pair with the 'colID'
// 3. make this into a pair and insert into the main map
i->second->insert(make_pair(ColID, new myObj(*Data)));
};
protected:
std::map <myVar, myRow *> * m_Rows;
}
int main()
{
myVar a, b, c, d;
myObj * o = new myObj();
o->setVar("test", a);
o->setVar("test2", b);
myTable * tab = new myTable();
myVar x1, y1, x2;
tab->addDataPoint(y1, x1, o);
o->release(); // this clears out both 'o' and the values in 'tab'!?!?
//at this point tab has no data in its object at y1,x1???
o->setVar("test3", c);
o->setVar("test4", d);
tab->addDataPoint(y1, x2, o);
}
What I'm noticing is that my data is deleted too early. I believe I've missed something... I had thought I was creating a copy of the data referenced by the pointer and then storing a newly instance'd pointer in my map... Any thoughts? I appreciate any help!
So one of the problems that using (owning) raw pointers in containers is that you need to manually delete the instances yourself. I presume that myObj::~myObj does just that (iterates the container deleting all elements before deleting the container itself).
The line:
i->second->insert(make_pair(ColID, new myObj(*Data)));
Is copy constructing a myObj from Data.
Unfortunately, because you are not defining a copy constructor for myObj the compiler will generate one for you which will just copy the pointer to the VarContainer member. It won't create a new copy of the map or anything that it refers to internally. Once a copy is created you then have two instances which both point to the same container and both instances think that they own it. When the first one gets destructed it will seem to ok but actually leaves the other instance pointing to freed memory. As soon as the longest lived instance tries to do anything using this container pointer something bad will happen.
You could fix this by storing the maps by value and not by pointer:
typedef std::map<std::string, myVar> myVarContainer;
typedef std::map<myVar, myObj> myRow;
Also change myObj::VarContainer to be a non-allocated member. This means that everything now gets copied correctly and a copy will not reference anything from the original.
Note that you can also use smart pointers (such as std::shared_ptr) instead of raw pointers but you will still need to be careful with that as, although copying would be safe, they share data with the original which might not be what you expect.
You should take a look at the following:
http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)
It seems that you are indeed creating a copy of the object, but then when you release(), you are releasing the VarContainer (deleting all items and using clear()), so the copy you created before (with a copy of the pointer, not the actual container) is left with a pointer to an empty container.

Storing local variable in std::map

I have a class Message and a class Cache.
In Message::processMessage() fn. I create a instance of another class CacheRef(not shown below.)
then I call Cache::cacheData(cacheRef)
Now, in Cache class, I have a map which has its key as CacheReference. I store the ref that I passed to cacheData fn. in this map.
class Message
{
private:
Key m_key;
public:
void processMessage(int a, int b, Cache *pCache)
{
CacheRef ref(a, b, m_key); //CacheRef is a class defined in same file
//some char *data - do processing an dfill it!!
pCache->cacheData(ref, data);
}
}
class Cache
{
public:
void cacheData(CacheRef &ref, const char* data)
{
CacheDir *dir;
std::map<<CacheRef, CacheDir*>::iterator it = m_dirs.find(ref);
if(it == m_dirs.end())
{
dir = new CacheDir();
m_dirs.insert(ref, dir);
}
}
std::map<CacheRef, CacheDir*> m_dirs; //CacheDir is some class defined in the same file
}
Now, the code is working absolutely fine. But I have this concern(not sure!!) that I am storing some local variable in map, which which cease to exist as soon as processMessage()fn. exits. So, am I accessing some invalid memory, is it just by luck that this code is working.
If this is wrong, what is the best way to achieve this behaviour?
I don't have boost on my system, so can't use shared_ptr for anything.
Because the 1st template parameter is a CacheRef (and not a reference or pointer to a CacheRef) then ref will be copied into the map when you do the insert. Hence, you won't be storing a reference to a local stack variable.
As long as there is an appropriate copy constructor or assignment operator for CacheRef then this will work ok.
As Stephen Doyle pointed out, you are actually storing a copy of the CacheRef in the map, not a reference to the one passed to the cacheData() method.
Whether this causes a problem or not depends on the definition of the CacheRef class. If, for example, a CacheRef holds a pointer or a reference to the Key passed to the constructor, you will end up with an invalid pointer once the Message instance is destroyed.
By the way, since you are storing dynamically allocated objects of CacheDir in Cache::m_dirs, you should make sure to delete all values in the map in the Cache::~Cache() destructor to avoid memory leaks.

C++ question about setting class variables

I'm not new to programming, but after working in Java I'm coming back to C++ and am a little confused about class variables that aren't pointers. Given the following code:
#include <iostream>
#include <map>
using namespace std;
class Foo {
public:
Foo() {
bars[0] = new Bar;
bars[0]->id = 5;
}
~Foo() { }
struct Bar {
int id;
};
void set_bars(map<int,Bar*>& b) {
bars = b;
}
void hello() {
cout << bars[0]->id << endl;
}
protected:
map<int,Bar*> bars;
};
int main() {
Foo foo;
foo.hello();
map<int,Foo::Bar*> testbars;
testbars[0] = new Foo::Bar;
testbars[0]->id = 10;
foo.set_bars(testbars);
foo.hello();
return(0);
}
I get the expected output of 5 & 10. However, my lack of understanding about references and pointers and such in C++ make me wonder if this will actually work in the wild, or if once testbars goes out of scope it will barf. Of course, here, testbars will not go out of scope before the program ends, but what if it were created in another class function as a function variable? Anyway, I guess my main question is would it better/safer for me to create the bars class variable as a pointer to the map map?
Anyway, I guess my main question is
would it better/safer for me to create
the bars class variable as a pointer
to the map map?
No. C++ is nothing like Java in this and may other respects. If you find yourself using pointers and allocating new'd objects to them a lot, you are probably doing something wrong. To learn the right way to do things, I suggest getting hold of a copy of Accelerated C++ by Koenig & Moo,
The member variable bars is a separate instance of a "dictionary"-like/associative array class. So when it is assigned to in set_bars, the contents of the parameter b are copied into bars. So there is no need to worry about the relative lifetimes of foo and testbars, as they are independent "value-like" entites.
You have more of a problem with the lifetimes of the Bar objects, which are currently never going to be deleted. If you add code somewhere to delete them, then you will introduce a further problem because you are copying the addresses of Bar objects (rather than the objects themselves), so you have the same object pointed to by two different maps. Once the object is deleted, the other map will continue to refer to it. This is the kind of thing that you should avoid like the plague in C++! Naked pointers to objects allocated with new are a disaster waiting to happen.
References (declared with &) are not different from pointers with regard to object lifetimes. To allow you to refer to the same object from two places, you can use either pointers or references, but this will still leave you with the problem of deallocation.
You can get some way toward solving the deallocation problem by using a class like shared_ptr, which should be included with any up-to-date C++ environment (in std::tr1). But then you may hit problems with cyclical pointer networks (A points to B and B points to A, for example), which will not be automatically cleaned up.
For every new you need a corresponding delete.
If you try and reference the memory after you call delete - where ever that is - then the program will indeed "barf".
If you don't then you will be fine, it's that simple.
You should design your classes so that ownership of memory is explicit, and that you KNOW that for every allocation you are doing an equal deallocation.
Never assume another class/container will delete memory you allocated.
Hope this helps.
In the code below you can pass map of Bars and then will be able to modify Bars outside of the class.
But. But unless you call set_bars again.
It is better when one object is responsible for creation and deletion of Bars. Which is not true in your case.
If you want you can use boost::shared_ptr< Bars > instead of Bars*. That will be more Java like behavior.
class Foo {
public:
Foo() {
bars[0] = new Bar;
bars[0]->id = 5;
}
~Foo() { freeBarsMemory(); }
struct Bar {
int id;
};
typedef std::map<int,Bar*> BarsList;
void set_bars(const BarsList& b) {
freeBarsMemory();
bars = b;
}
void hello() {
std::cout << bars[0]->id << std::endl;
}
protected:
BarsList bars;
void freeBarsMemory()
{
BarsList::const_iterator it = bars.begin();
BarsList::const_iterator end = bars.end();
for (; it != end; ++it)
delete it->second;
bars.clear();
}
};
I'm not new to programming, but after working in Java I'm coming back to C++ and am a little confused about class variables that aren't pointers.
The confusion appears to come from a combination of data that is on the heap and data that is not necessarily on the heap. This is a common cause of confusion.
In the code you posted, bars is not a pointer. Since it's in class scope, it will exist until the object containing it (testbars) is destroyed. In this case testbars was created on the stack so it will be destroyed when it falls out of scope, regardless of how deeply nested that scope is. And when testbars is destroyed, subobjects of testbars (whether they are parent classes or objects contained within the testbars object) will have their destructors run at that exact moment in a well-defined order.
This is an extremely powerful aspect of C++. Imagine a class with a 10-line constructor that opens a network connection, allocates memory on the heap, and writes data to a file. Imagine that the class's destructor undoes all of that (closes the network connection, deallocates the memory on the heap, closes the file, etc.). Now imagine that creating an object of this class fails halfway through the constructor (say, the network connection is down). How can the program know which lines of the destructor will undo the parts of the constructor that succeeded? There is no general way to know this, so the destructor of that object is not run.
Now imagine a class that contains ten objects, and the constructor for each of those objects does one thing that must be rolled back (opens a network connection, allocates memory on the heap, writes data to a file, etc.) and the destructor for each of those objects includes the code necessary to roll back the action (closes the network connection, deallocates objects, closes the file, etc.). If only five objects are successfully created then only those five need to be destroyed, and their destructors will run at that exact moment in time.
If testbars had been created on the heap (via new) then it would only be destroyed when calling delete. In general it's much easier to use objects on the stack unless there is some reason for the object to outlast the scope it was created in.
Which brings me to Foo::bar. Foo::bars is a map that refers to objects on the heap. Well, it refers to pointers that, in this code example, refer to objects allocated on the heap (pointers can also refer to objects allocated on the stack). In the example you posted the objects these pointers refer to are never deleted, and because these objects are on the heap you're getting a (small) memory leak (which the operating system cleans up on program exit). According to the STL, std::maps like Foo::bar do not delete pointers they refer to when they are destroyed. Boost has a few solutions to this problem. In your case it's probably be easiest to simply not allocate these objects on the heap:
#include <iostream>
#include <map>
using std::map;
using std::cout;
class Foo {
public:
Foo() {
// normally you wouldn't use the parenthesis on the next line
// but we're creating an object without a name, so we need them
bars[0] = Bar();
bars[0].id = 5;
}
~Foo() { }
struct Bar {
int id;
};
void set_bars(map<int,Bar>& b) {
bars = b;
}
void hello() {
cout << bars[0].id << endl;
}
protected:
map<int,Bar> bars;
};
int main() {
Foo foo;
foo.hello();
map<int,Foo::Bar> testbars;
// create another nameless object
testbars[0] = Foo::Bar();
testbars[0].id = 10;
foo.set_bars(testbars);
foo.hello();
return 0;
}