如何使用 std::move() 将 char[] 移动到向量<char>

How to use std::move() to move char[] to a vector<char>

本文关键字:char 向量 std lt gt 何使用 移动 move      更新时间:2023-10-16

我正在尝试将两个字符数组char a[9000]; char b[9000]连接到容器std::vector<char>。由于阵列大小不小。我正在尝试使用std::move()

class obj
{
public:
obj &operator <<(char *&&ptr)
{
//???
ptr = nullptr;
return *this;
}
private:
std::vector<char> m_obj;
};

所以在主函数中

int main()
{
obj o;
enum {SIZE=9000};
char a[SIZE]; memset(a, 1, SIZE);
char b[SIZE]; memset(b, 2, SIZE);
o << a << b;
return 0;
}

我的问题是移动字符*的正确方法是什么?


环境
优麒麟 16.04.4 LTS
g++ 5.4.0

tl;博士

拨打reserve()并复制。

搬家怎么了?

几件事。首先,你似乎对std::move的期望是错误的。std::move不会神奇地移动任何东西(或者根本不移动任何东西,包括非魔法(。它的作用是强制转换为右值引用,这在某些情况下可能允许移动。

其次,从 C++03 开始,std::vector保证其元素连续地排列在内存中(在 C++03 之前,无论如何都是事实,但没有给出明确的保证(。如果您使用std::move那么您必须使用晚于 C++03 的版本,因此std::vector必须连续布置其元素.
这意味着除了两个数组恰好彼此相邻的完全巧合的情况之外,没有办法在不复制的情况下将两个数组中的元素放入向量中。根本无法移动它们,因为必须至少重新定位一个数组(= 复制(。

此外,我无法想象如何以您打算的方式从数组中移动元素。移动假定您接管了所有权,这通常意味着您以某种方式修改了 moved-from 对象,使其仍然有效,但之前没有任何资源。
如何处理在周围范围内具有自动存储持续时间的数组?那么在移动后取消引用数组(这是可能的和合法的(将做什么?

此外,你想把一个数组衰减到一个指针上(这是完全合法的(,然后以某种方式神奇地移动。但是,这不会移动数组的内容!你能做的最好的事情就是移动指针,但这没有意义,因为移动指针与复制指针是一样的。

您无法绕过必须复制数组元素,但您可以通过提前正确调用reserve()来节省一个内存分配和一个不必要的副本。

好吧,char* 并不是你想要移动的对象。因此,获取对指针的右值引用并不完全有帮助。 你为什么不尝试类似数组的移动方式并使用std::move from "algorithm"?

http://en.cppreference.com/w/cpp/algorithm/move

它看起来像这样:

obj& obj::addChars(char *ptr, size_t size = 9000u) {    
m_obj.resize(size);
std::move(ptr, ptr + size, m_obj.begin());
return *this;
}

以下工作是因为向量是连续内存。 有必要调整矢量的大小以容纳要复制的元素的数量。

&vc[0] 是向量第 0 个元素的内存地址。 &vc[SIZE] 是向量第 9000 个元素的内存地址,数组 b 应该从那里开始。

这将比尝试遍历数组和push_back或分配矢量元素快得多。

enum {SIZE=9000};
char a[SIZE];
memset(a, 1, SIZE);
char b[SIZE];
memset(b, 2, SIZE);
// make a vector of characters
std::vector<char> vc;
// resize to hold two arrays
vc.resize(SIZE * 2);
// copy array a to the beginning of the vector
memcpy(&vc[0], a, SIZE);
// copy array b to the end of the vector
memcpy(&vc[SIZE], b, SIZE);

编辑:

std::vector<char> vc(SIZE * 2);

与创建相同,然后调整大小。 它将创建具有指定大小的矢量,然后不需要调整大小。

即使您使用new分配了数组,也无法获得 vector 来采用数组。将进行复制。

推荐的方法std::copy在大多数实现中将被认为是可优化的std::memcpy()

#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#define SIZE 90
int main(void) {
std::vector<char> v;
v.resize(2*SIZE);
char a[SIZE]; 
char b[SIZE]; 
std::memset(a, 'a', SIZE);
std::memset(b, 'b', SIZE);
std::copy(a,a+SIZE,v.begin());
std::copy(b,b+SIZE,v.begin()+SIZE);
for(char c : v){
std::cout << c;
}
std::cout << std::endl;
return 0;
}

如果不是这样优化(不太可能(,请使用std::memcpy().

如何在课堂上实现这一点是另一个争论。 您可以实现add(char *start,char *end);成员。

正如其他人指出的那样,9000char并不大,如果你做得更多,你可能会过度设计。

进一步的扩展将允许您在矢量中resize()reserve()大小,以避免在第二次复制期间不可避免的调整大小。