为什么我不能记住std :: string?

时间:2013-06-06 06:29:59

标签: c++ memmove

#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();
}

运行代码。如您所见,当调用string的desctrutor时程序崩溃。尝试评论delete的行并再次检查。

我怀疑std :: string会保留一些自己的地址信息。当它在内存中的位置发生变化时,它不会被告知。

此外,由于memmove并不总是按预期工作,因此在C ++中复制类实例数组的适当表达是什么?

4 个答案:

答案 0 :(得分:1)

memmove是用于复制字节的低级函数。这意味着将字节数组的值复制到另一个数组。这适用于POD数据,但不适用于其他任何内容。原因是类可以有一个复制构造函数,memmove不会调用它,类可以有一些额外的数据,比如用于调用虚拟成员函数的vpointer。

最简单的解决方案是将memmove替换为std::copy#include <algorithm>),复制条目而不是字节:

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

答案 1 :(得分:1)

我相信你要找的是string::reserve

在你的代码中,你也试图创建一个字符串数组(而不是字符串作为字符数组)。

你在这里做的是复制对象'string',而不是它的内容(因为你没有调用它的构造函数/析构函数)。 因此,当您'删除'您的“arr_ptr”时,析构函数释放相关的数据。 当您尝试使用tmp_ptr访问它时,程序会出现段错误。

答案 2 :(得分:0)

1,您没有初始化您的容量值,如:

int capacity;

应该是:

int capacity = 0;

当您尝试此操作时:

arr_ptr[capacity - 1] = "occupied";

可能会发生引用错误。

答案 3 :(得分:0)

此程序的行为依赖于::std::string实现。

如果字符串的实现使用堆内存来存储字符,memmove字符串实例意味着有两个指向同一堆内存的指针。调用其中一个字符串实例的析构函数会导致释放堆内存,从而导致另一个字符串实例具有悬空指针。

所以不要memmove字符串:)