【问题标题】:Using memcpy to copy the contents of a vector<double> into a memory buffer使用 memcpy 将 vector<double> 的内容复制到内存缓冲区中
【发布时间】:2014-03-24 15:15:44
【问题描述】:

我有一个包装矢量的类:

template <typename T>
class PersistentVector
{
  private:
    std::vector<T> values;
  public:
    std::vector<T> & getValues() throw () { return values; }
....
}

实例是:

PersistentVector<double> moments;

我正在尝试将所有双打副本复制到其他人分配的缓冲区中。这是我创建缓冲区的地方:

// invariant: numMoments = 1
double * data_x = new double[numMoments];

这是我将向量的内容复制到缓冲区的尝试:

double theMoment = moments.getValues()[0];
// theMoment = 1.33

std::memcpy(
  data_x, 
  &(moments.getValues().operator[](0)), 
  numMoments * sizeof(double));
// numMoments = 1

double theReadMoment = data_x[0];
// theReadMoment = 6.9533490643693675e-310

如您所见,我从缓冲区中获取了一个垃圾值。为什么会这样?

工作解决方案

使用std::copy(感谢 WhozCraig)

double theMoment = moments.getValues()[0];
// theMoment = 1.33

std::copy(moments.getValues().begin(), moments.getValues().end(), data_x);

double theReadMoment = data_x[0];
// theReadMoment = 1.33

失败的解决方案

尝试data() 而不是operator[]()

double theMoment = moments.getValues()[0];
// theMoment = 1.33 

std::memcpy(
  data_x, 
  moments.getValues().data(),
  numMoments * sizeof(double));
// numMoments = 1

double theReadMoment = data_x[0];
// theReadMoment = 6.9533490643693675e-310

仍然对为什么我的原始代码失败感到好奇!

【问题讨论】:

  • std::copy(moments.getValues().begin(), moments.getValues().end(), data_x) ?还是我错过了一些明显的东西? (仅供参考,像“invariant: numMoments = 1”这样的东西令人欣慰的是,看看这是否真的是一个指向 single double 的指针)。
  • 尝试将 .operator[](0) 替换为 .data()。
  • @Ben no,它确实not
  • @Ben 如果不是普通类型,yes(或赋值运算符等)。如果目标不是诸如插入或后推迭代器之类的东西,则分配(通常)是展开的,否则放置通常是最喜欢的优化。
  • @WhozCraig 为什么不让您的 cmets 成为答案?这是一个常见的陷阱,详细说明对许多用户来说肯定是有价值的。顺便说一句,如果 memcpy 以相反的方式执行 - 从标准数组到向量(内存损坏),问题会更大,更难调试。

标签: c++


【解决方案1】:

我尝试了 3 种不同的方式来做这件事,所有的方法都奏效了。 data() 方法是正确执行此操作的方法。 如果它不起作用 - 检查数据是否以某种方式损坏。

 std::vector<double> vec1 = {1.33,2.66,3.99};
 double* vec2 = new double[3];

 int numMoments = 1;

 ::memcpy(
  vec2, 
  vec1.data(),
  numMoments * sizeof(double));

 ::memcpy(
  vec2, 
  &(*vec1.begin()),
  numMoments * sizeof(double));

 ::memcpy(
  vec2, 
  &(vec1[0]),
  numMoments * sizeof(double));

【讨论】:

  • 在第二个 memcpy 中,你同时使用 & 和 *。您可以等效地编写 ::memcpy(ve2, vec1.begin(), numMoments * sizeof(double)); AFAIK。
  • @batbrat 它不像你建议的那样工作,因为 begin 返回的迭代器不能转换为 void*。
  • 看了你的评论后,我捂着脸。不是我最美好的时刻。谢谢你提醒我。
猜你喜欢
  • 2011-12-24
  • 1970-01-01
  • 1970-01-01
  • 2022-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多