我正在使用memmove
将std::string
元素向右移动一个点。目的地的第一个地方是唯一被弄乱并充满垃圾的地方。我使用的是memmove
而不是strcpy
,因为我在需要模板的类中使用它。当我有一系列的int时,它工作正常。关于如何解决这个问题的任何想法?
/**
* @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]
答案 0 :(得分:6)
当您的数组包含memcpy
个对象时,memmove
和std::string
都不可能。原因是当它们不应该篡改对象的内部时(C ++对象的完整性由其构造函数/赋值运算符/析构函数/成员函数确保,您必须修改其字节除非你确切知道你做了什么,否则请手动。
正如已经建议的那样,使用一个方法来考虑构造函数,赋值运算符和析构函数(例如std::copy_backward
)或者更好的方法,摆脱那些遗留的C数组并使用适当的C ++容器,如{{1}并使用容器的函数来插入/删除项目。
换句话说,一旦你开始使用C ++对象,你就必须开始编写C ++,而不再是“C with classes”。
答案 1 :(得分:2)
换句话说,为了避免溢出,两者都指向了数组的大小 目的地和源参数,至少应为num个字节,和 不应该重叠(对于重叠的内存块,memmove是更安全的 方法)。
使用memmove。
答案 2 :(得分:1)
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
代替。
答案 3 :(得分:1)
如图书馆文档中所述,您不能将memcpy
用于重叠范围:
7.21.2复制功能
7.21.2.1 memcpy函数
...
2 memcpy函数将s2指向的对象中的n个字符复制到s1指向的对象中。如果在重叠的对象之间进行复制,行为未定义。
7.21.2.2 memmove功能
...
2 memmove函数将s2指向的对象中的n个字符复制到 s1指向的对象。复制就像对象中的n个字符一样 由s2指向的第一个被复制到n个字符的临时数组中 重叠s1和s2指向的对象,然后重写n个字符 临时数组被复制到s1指向的对象中。
对于POD或平凡初始化类型,您可以使用memmove
(如上所述)或std::copy_backward
(只要最后一个目标元素不在源范围内)
This question更多地讨论了memcpy-vs-memmove部分。
对于std::string
等非平凡类型,您无法使用memcpy
或 memmove
,但必须使用std::copy
或std::copy_backward
。
答案 4 :(得分:1)
与此处的大多数人一样,您可以使用memmove
代替memcpy
,因为它可以处理重叠范围。
然而,C ++解决方案将使用copy_backward
,它明确地显示了您的要求,并将在屏幕后面为您选择最快的复制方法。这看起来像这样:
std::copy_backward(std::begin(_array)+newItem, std::end(_array)-1, std::end(array));
这意味着您将从前一个到后一个元素向后复制到newItem的位置,并从后面开始插入。这显然可以处理这种需要的重叠。可能是屏幕后面的memmove或其他特定于平台的内存副本。