Search code examples
c++memmove

Why can't I memmove std::string?


#include <cstdlib>
#include <cstring>
#include <string>

using std::string;

string *arr_ptr;
int capacity;

void add() {
    int old_capacity = capacity;
    capacity <<= 1; 
    // double the capacity
    string *tmp_ptr = new string[capacity]; 
    // apply new space
    memmove(tmp_ptr, arr_ptr, sizeof(string) * old_capacity);
    // copy
    delete[] arr_ptr; 
    // free the original space
    arr_ptr = tmp_ptr;

    arr_ptr[capacity - 1] = "occupied";
    // without this statement, everything "seems" to be fine.
}

int main() {
    arr_ptr = new string[1];
    capacity = 1;
    for (int i = 0; i < 3; i++) add();
}

Run the code. As you can see, the program crashes when string's desctrutor is invoked. Try to comment the line of delete and check again.

I suspect that std::string keeps some address information of itself. It won't be informed when its location in memory has changed.

Furthermore, since memmove doesn't always work as expected, what's the appropriate expression of copying an array of class instance in C++?


Solution

  • memmove is a lowlevel function for copying bytes. This means that the value of an array of bytes is copied to another array. This is fine for POD data, but not for anything else. The reason is that classes can have a copy constructor, which isn't called by memmove and classes can have extra data like a vpointer for calling virtual member-functions.

    The easiest solution for you is to replace memmove with std::copy for (#include <algorithm>) which copies entries instead of bytes:

    std::copy(arr_ptr, arr_ptr + old_capacity, tmp_ptr);