Reputation: 2224
I have the following problem:
void add(){
cRow Row();
Row.add("Column", "Value");
std::vector<cRow> mRows;
mRows.push_back(Row);
}
cRow::cRow(): mCol(NULL), mVal(NULL) {
}
cRow::add(const char* Col, const char* Val){
mCol = strdup(Col);
mVal = strdup(Val);
}
cRow::~cRow(){
free(mCol);
free(mVal);
}
After adding the local variable Row to the vector, the destructor is called for that Row and the strings are freed.
Obviously, the pointers to the strings of the stored row in the vector are now freed as well. Any access to the rows after leaving the local scope will result in segfaults.
The dump of the rows looks after 2 calls like that:
| (null) | (null) |
-----------------------------------------------------
| (null)| (null) |
| LastContainerUpdatePropagation| 1307967498 |
------------------------ END ------------------------
after 3 calls:
| (null) | (null) |
-----------------------------------------------------
| (null)| (null) |
| (null)| (null) |
| LastSystemUpdatePropagation| 1307967498 |
------------------------ END ------------------------
and after leaving the scope completely without adding a new row, every row was freed.
So, now my question: How does std:vector copy objects? What do I have to do to keep the pointers to the strings or to copy them into another space?
Thank you very much!
Upvotes: 2
Views: 1621
Reputation: 231193
std::vector
uses the copy constructor to copy objects. Since you have not defined a copy constructor, it will use the implicit C++ copy constructor, which just copies all members recursively; this isn't enough, since you are manually managing memory.
You need to either define your own copy constructor, or use something like std::string
, which will do the right thing if copied.
As a matter of good practice, any class with a non-trivial destructor should have a copy constructor and copy assignment operator, for precisely this reason (this is known as the rule of three). If a copy constructor doesn't make sense (eg, for things like ostream
), it should be made private, in order to prevent accidental copying.
Upvotes: 9
Reputation: 3509
std::vector
uses the copy constructor to initialise its elements. If you haven't written on explicitly, the compiler provides one, but as you are doing memory management, you need to either:
cRow
class (note that you will still need to provide the appropriate copy constructor, copy assignment operator and destructor for your RAII container).const char*
, which could be replaced with std::string
, which will handle the memory management.Note: only approach #3 avoids having to write a custom version of the three functions.
Upvotes: 2