【问题标题】:Why can't I memmove std::string?为什么我不能 memmove std::string?
【发布时间】:2013-06-06 06:29:58
【问题描述】:
#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();
}

运行代码。如您所见,调用字符串的析构函数时程序崩溃。尝试评论delete这一行并再次查看。

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

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

【问题讨论】:

  • 必须第二个克里斯。不要将 char 样式的数组旧样式与“新”(好吧)stl 容器/类混合。
  • @chris 我正在为我的数据结构类写作业。 XD

标签: c++ memmove


【解决方案1】:

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

最简单的解决方案是将memmove 替换为std::copy for (#include &lt;algorithm&gt;),它复制条目而不是字节:

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

【讨论】:

    【解决方案2】:

    我相信您正在寻找的是string::reserve

    在您的代码中,您还尝试创建一个字符串数组(而不是将字符串作为字符数组)。

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

    【讨论】:

      【解决方案3】:

      第一个你没有初始化你的容量值:

      int capacity;
      

      应该是:

      int capacity = 0;
      

      当你尝试这个操作时:

      arr_ptr[capacity - 1] = "occupied";
      

      可能会出现引用错误。

      【讨论】:

        【解决方案4】:

        此程序的行为取决于::std::string 实现。

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

        所以不要memmove字符串:)

        【讨论】:

        • 你能详细解释一下吗:“memmove一个字符串实例意味着有两个指针指向同一个堆内存”?
        猜你喜欢
        • 2022-01-20
        • 2021-10-27
        • 1970-01-01
        • 1970-01-01
        • 2020-12-05
        • 2018-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多