开发者

How does std::vector copy objects to its internal storage

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) |
| LastC开发者_JAVA百科ontainerUpdatePropagation| 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!


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.


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:

  1. Provide a copy constructor, copy assignment operator and destructor (see the Rule of Three)
  2. Use RAII and create a small wrapper that handles all the memory management for a single value, and use as many of those as required in your cRow class (note that you will still need to provide the appropriate copy constructor, copy assignment operator and destructor for your RAII container).
  3. Use a type that handles the memory for you, in your example, you are using 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜