我有一个函数,我想用它来将双精度数组转换为双精度数:
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
为什么?
答案 0 :(得分:6)
你的问题是memcpy期望一个字节大小,而不是元素数,所以你需要将第三个参数乘以sizeof(double)
,但实际上你应该做的是使用vector的构造函数,它需要两个迭代器,如此:
std::vector<double> y(x, x + 3);
这样你就不用担心尺寸而且它更短了!
或者您也可以使用std::copy
(如我的评论/其他答案中所述,但无缘无故更长)
答案 1 :(得分:2)
您需要使用:
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;
}
答案 2 :(得分:2)
请勿使用memcpy
复制到std::vector
,效率低且容易出错。
效率较低,因为在构造或调整向量时,它会使用值初始化元素(除非您提供一个元素)填充新元素,对于算术类型,该元素为0。但是,初始化是不必要的,因为您随后会覆盖这些值。初始化可能很便宜,但它不是免费的。
std::vector
有一个构造函数,它接受两个迭代器,正如其他人已经提到的那样,复制输入范围。这个构造函数避免了在复制之前不必要的默认初始化。
std::vector
还有assign
和insert
个成员函数,它们接收两个迭代器并有效地复制输入范围。 v.append(beg, end)
为v.insert(v.end(), beg, end)
。
在我看来,在C ++代码中使用memset
,memcpy
和memmov
始终是一个错误。
这些函数由标准C库实现,因此丢失输入参数类型/对齐信息(因为它们采用void*
)。在切换到最合适的SIMD版本之前,他们需要在运行时检查参数的对齐和大小。未对齐的开头和结尾由非SIMD指令处理。
虽然C ++编译器知道类型的对齐和大小,但是内联生成适当的SIMD指令,而没有C库函数所做的那些对齐和大小检查。同样,这些检查可能很便宜,但它们不是免费的。
C ++算法(如std::copy
,std::copy_backward
,std::fill
和带有两个迭代器的容器复制函数会自动将这些C原语函数用于POD类型。
{}
中的double buf[N] = {};
等C ++初始化表达式为您做memset
,但同样,更高效,更不容易出错。
答案 3 :(得分:1)
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
作为已分配的数组。