使用memcpy将std :: vector复制到protobuf的重复字段

时间:2013-03-19 12:33:00

标签: c++ protocol-buffers memcpy

起初我有这个简单的protobuf文件

message messagetest
{
    ...
    repeated float samples = 6;
    ....
}

使用此方法创建头文件  

    //repeated float samples = 6;
      inline int samples_size() const;
      inline void clear_samples();
      static const int kSamplesFieldNumber = 6;
      inline float samples(int index) const;
      inline void set_samples(int index, float value);
      inline void add_samples(float value);
      inline const ::google::protobuf::RepeatedField< float >&  samples() const;
      inline ::google::protobuf::RepeatedField< float >* mutable_samples();

我基本上做的是在for循环中逐个复制所有数据。

int main(int argc, char** argv)
{    
    messagetest fMessage;

    vector<float> fData (1000, 0);

    // Create 1000 random values
    for (int i = 0; i < fData.size(); i++)
    {
        fData[i] = rand() % 1001;
    }

    for (int j = 0; j < fData.size(); j++)
    {
        fMessage.add_samples(fData[j]);    
    }

    return 0;
}

但我想使用像memcpy这样的方法来加速复制过程。这只是我想到的一个想法。如果这是完全错误的纠正我。 头文件中的最后一个声明是:

inline ::google::protobuf::RepeatedField< float >* mutable_samples();

我不知道这种方法的作用(缺乏技巧)。但它看起来像一个矢量。也许这是我的问题的解决方案。如果是这样,我不知道如何实现它。


编辑已解决

Memcpy在任何情况下都更快,因为你有一个方法调用,然后你复制数据。与for循环相比,必须调用“fMessage.add_samples()”方法1000次。

这种方法的一个缺陷是您必须知道向量的大小以保留样本的数据,但是您可以在程序中分配启动fMessage.sample的内存(这适用于我)。

fMessage.mutable_samples()->Reserve(fData.size());

for (int j = 0; j < fData.size(); j++)
{
   fMessage.add_samples(0);          
}

现在我可以在while循环中从流中获取数据并将它们与memcpy一起复制到我的数据表中

while(42)
{
   //fancy streaming things to get vector fData

  memcpy(fMessage.mutable_samples()->mutable_data(),
         &fData[0],
         sizeof(float)*fData.size());
}

4 个答案:

答案 0 :(得分:16)

由于这还没有,我喜欢单行:

*fMessage.mutable_samples() = {fData.begin(), fData.end()};

答案 1 :(得分:15)

我找到了将矢量复制到重复字段的最短路径:

google::protobuf::RepeatedField<float> data(fData.begin(), fData.end());
fMessage.mutable_samples()->Swap(&data);

它可能也比你的更快,因为它避免了初始迭代并将值设置为0

答案 2 :(得分:0)

fMessage.mutable_samples()

返回样本的指针数组:[* sample1,* sample2,sample3,...]。

&fData[0]

是fData的第一个元素的地址。

memcpy(fMessage.mutable_samples()->mutable_data(),
     &fData[0],
     sizeof(float)*fData.size());

因此,我认为上面的代码无法成功地将数据从fData填充到fMessage。完全错了!

答案 3 :(得分:0)

@mgild 的回答将隐式调用 RepeatedField(Iter begin, Iter end) 构造函数来创建一个临时的移动分配。与@nazgul 的回答相同,它明确创建一个临时的 RepeatedField 并交换它。

更简单,避免创建新对象是:

fMessage.mutable_samples()->Add(fData.begin(), fData.end())

如果 samples 字段已经不为空,您可以先调用 Clear 方法。

在内部,这使用 std::copy(只要 fDataforward iterator),因此与您提出的任何 memcpy 实现一样快。