用于将数组转换为矢量的内存

Memcpy for converting array to vector

本文关键字:内存 数组 转换 用于      更新时间:2023-10-16

我有一个函数,我想用它来将双精度数组转换为双精度向量:

std::vector<double> ArrayToVector(const double* arr, int length)
{
std::vector<double> vec(length);
memcpy(&vec[0], &arr[0], length);
return vec;
};

但是当我运行时:

int main()
{
double* x = new double[3];
x[0] = 2;
x[1] = 4;
x[2] = 6;
std::vector<double> y = ArrayToVector(x, 3);
for (int i = 0; i < 3; i++)
{
std::cout << y[i] << " ";
}
return 0;
}

我得到输出:

0 0 0

而不是

2 4 6

为什么?

你的问题是memcpy期望一个以字节为单位的大小,而不是元素的数量,所以你需要将第三个参数乘以sizeof(double)但实际上你应该做的是使用向量的构造函数,它需要两个迭代器,如下所示:

std::vector<double> y(x, x + 3);

这样你甚至不需要担心大小,而且它更短!

或者,您可以使用std::copy(如我的评论/另一个答案中所述,但无缘无故地更长)

不要使用memcpy复制到std::vector中,效率较低且容易出错。

它的效率较低,因为当您构造或调整向量大小时,它会使用值初始化的元素填充新元素(除非您提供一个元素),算术类型为 0。但是该初始化是不必要的,因为随后会覆盖这些值。这种初始化可能很便宜,但它不是免费的。

std::vector有一个构造函数,它接受两个迭代器,正如其他人已经提到的,它们复制输入范围。此构造函数避免了复制前不必要的默认初始化。

std::vector还具有assigninsert成员函数,这些函数采用两个迭代器并有效地复制输入范围。v.append(beg, end)v.insert(v.end(), beg, end).


在我看来,在C++代码中使用memsetmemcpymemmov总是一个错误。

这些函数由标准 C 库实现,因此会丢失输入参数类型/对齐信息(因为它们需要void*)。在切换到最合适的 SIMD 版本之前,他们需要在运行时检查参数的对齐方式和大小。未对齐的开头和结尾由非 SIMD 指令处理。

而C++编译器知道类型的对齐方式和大小,并内联生成适当的 SIMD 指令,而无需像 C 库函数那样进行对齐和大小检查。同样,这些支票可能很便宜,但它们不是免费的。

C++算法,如std::copystd::copy_backwardstd::fill和容器复制函数,需要两个迭代器,这些C原语函数会自动用于POD类型。

C++初始值设定项表达式(如{}indouble buf[N] = {};)为您memset,但同样,以更高效且更不容易出错的方式。

您需要使用:

memcpy(&vec[0], &arr[0], length*sizeof(double));

或者更好的是,使用:

int main()
{
double* x = new double[3];
x[0] = 2;
x[1] = 4;
x[2] = 6;
std::vector<double> y(x, x+3);    
for (int i = 0; i < 3; i++)
{
std::cout << y[i] << " ";
}
return 0;
}

memcpy 复制字节。因此,您必须指定要复制的字节数(而不是双精度数)。

memcpy(&vec[0], &arr[0], length * sizeof( double ) );

然而,这种方法是不好的。最好按以下方式定义向量

std::vector<double> ArrayToVector(const double* arr, int length)
{
return { arr, arr + length };
}

std::vector<double> ArrayToVector(const double* arr, int length)
{
std::vector<double> vec( arr, arr + length );
return vec;
}

考虑到您需要为阵列释放分配的内存。例如,您可以对分配的数组使用智能指针std::unique_ptr