0

memmove用来将std::string元素向右移动一个位置。目的地的第一个地方是唯一一个被弄乱并充满垃圾的地方。我使用memmove而不是strcpy因为我在需要模板的类中使用它。当我有一个整数数组时它工作正常。关于如何为字符串解决此问题的任何想法?

/**
 * @brief Shifts elements in the array to the right
 * @param newItem The insert position.
 */
template<class T>
void DynamicArray<T>::shiftElementsRight(uint newItem) {
    uint diff = _size - newItem;
    memmove(&(_array[newItem + 1]),
            &(_array[newItem]), sizeof(_array[0]) * diff);
}

我的主要

int main() {
    DynamicArray<string> array(1);

    string val1 = "val1";
    array.add(val1);
    string val2 = "val2";
    array.add(val2);
    // ... more additions ...

最后的输出:

Sizeof: 8
Value is: val1
Value is: val11val3, val21
                            ����[val1, val2A����[val1, val2, val31val4, Aq�����[val1, val2, val3 val4, val5Q`r�#����[val1, val2, val3, val4, val5, val61val5, 1val6, Q"����[val1, val2, val3, al4, a
8s��p�hp��p�hq�(r�Xr�؄KC�؄KC�؄KC�1val7, a:����[val1, val2, val3, val4, val5, qF����[val1, val2, val3, val4, val5, val6]
4

5 回答 5

6

当您的数组包含对象时,既不可能memcpy也不可能。原因是两者都在不应该篡改对象的内部时(C++ 对象的完整性由其构造函数/赋值运算符/析构函数/成员函数确保,除非您确切知道自己的内容,否则不得手动修改其字节做)。memmovestd::string

正如已经建议的那样,使用一种将构造函数、赋值运算符和析构函数考虑在内的方法(std::copy_backward例如),或者更好的是,摆脱那些遗留的 C 数组并使用适当的 C++ 容器,例如vector并使用容器的函数来插入/删除项目。

换句话说,一旦你开始使用 C++ 对象,你就必须开始编写 C++,而不是“C with classes”了。

于 2013-10-18T07:37:08.400 回答
2

来自memcpy 描述

为避免溢出,目标和源参数指向的数组大小至少应为 num 字节,并且不应重叠(对于重叠的内存块,memmove 是一种更安全的方法)。

换句话说,使用memmove 。

于 2013-10-18T07:07:44.260 回答
1

就像这里的大多数人说的那样,您可以使用memmove而不是memcpy因为它可以处理重叠范围。

但是,C++ 解决方案是使用copy_backward,它会明确执行您的要求,并将在屏幕后面为您选择最快的复制方法。看起来像这样:

std::copy_backward(std::begin(_array)+newItem, std::end(_array)-1, std::end(array));

这意味着您将从上一个到最后一个元素向后复制到位置 newItem 并将从后面开始插入。这显然可以处理所需的重叠。可能是在屏幕后面使用 memmove 或其他特定于平台的内存副本。

于 2013-10-18T07:23:23.747 回答
0
 SYNOPSIS
        #include <string.h>

        void *memcpy(void *dest, const void *src, size_t n);

 DESCRIPTION
        The  memcpy()  function  copies  n bytes from memory area src to memory
        area dest.  The memory areas must not overlap.  Use memmove(3)  if  the
        memory areas do overlap.

您的内存区域不能重叠,否则memcpy' 的行为未定义。你应该memmove改用。

于 2013-10-18T07:08:41.053 回答
0

memcpy如库文档中所述,您不得使用重叠范围:

7.21.2 复制功能

7.21.2.1 memcpy 函数

...

2 memcpy函数将n个字符从s2指向的对象复制到s1指向的对象中。如果复制发生在重叠的对象之间,则行为是 undefined

7.21.2.2 memmove 函数

...

2 memmove函数将n个字符从s2指向的对象复制到s1指向的对象中。复制过程就像先将 s2 指向的对象中的 n 个字符复制到不与 s1 和 s2 指向的对象重叠的 n 个字符的临时数组中,然后将临时数组中的 n 个字符复制到s1 指向的对象。

对于 POD 或简单初始化的类型,您可以使用memmove(如上所述)或std::copy_backward(只要最后一个目标元素不在源范围内)

这个问题有更多关于 memcpy-vs-memmove 部分的讨论。

对于非平凡的类型,例如std::string,您不能使用memcpy or memmove,但必须使用std::copyor std::copy_backward

于 2013-10-18T07:08:54.027 回答