在C ++ 11中从向量复制到结构中

时间:2015-10-29 01:14:58

标签: c++ c++11

在C ++ 11中,执行以下代码的最佳方法是什么:

// definitions
vector<char> rcvbuf; 

 struct somethingParams
{
  char Magic[4]; 
  int Version; 
  int MsgID; 
  int MsgLen;
};

代码:

struct somethingParams mParams; 
memcpy(&mParams, rcvbuf.data(), sizeof(somethingParams)); 
rcvbuf.erase(rcvbuf.begin(), rcvbuf.begin + sizeof(somethingParams));

根据我的阅读,不建议在C ++中使用memcpy。我知道它是&#34; C风格&#34;。有没有更好的方法来实现我正在做的事情? (即将数据从矢量复制到结构中。)

只是看看我能不能做得更多&#34; C ++&#34;。

感谢。

2 个答案:

答案 0 :(得分:5)

memcpy是C ++中的犹太人。当然它不应该用于制作数组的副本(我们有std::copy,以及向量和其他有趣的东西)但是从二进制数据初始化结构的情况本质上是类型不安全的C ++并没有在这里给你提供C不能做的任何事情。

但是,您必须记住仅使用简单的可复制类型memcpy。您可以使用static_assert确保不要违反此规则并触发未定义的行为。

static_assert(std::is_trivially_copyable<somethingParams>::value,
              "somethingParams must be trivially copyable");

答案 1 :(得分:1)

您的代码令人困惑。一方面,您有vector char个{长度n。)

你有一个结构,其中char数组长度为4,int

我看不出 blind memcpy会带来什么样的合理结果。

但也许我可以唤起一些可以帮助你进一步挖掘的想法:

  1. vectorchar个元素可能被string个对象取代? string对象用于在内部保存char数组。我认为这更多是C ++,但取决于你的要求。
  2. memcpy只是复制内存。我不确定这是不是你想要的;我认为复制后结构包含垃圾。在我看来不可预测。
  3. 要从容器中复制(vector是STL容器),在C ++中执行此操作的标准方法(除上述std::copy函数外)是迭代元素并复制它们。见下文。
  4. 最熟悉迭代器:

    for (vector<char>::iterator it = rcvbuf.begin(); it != rcvbuf.end(); it++) {
        //copy element *it into something
    }
    

    C ++ 11引入了循环自动范围:

    for (auto elem : rcvbuf) {
        //copy element elem into something
    }
    

    进一步阐述:

    该向量包含16个元素。第4个元素是空字符,用于模拟C样式字符串的结尾。如果没有null字符,char数组也会包含垃圾。

    为简单起见,我删除了erase。它只是擦除指定范围内的元素(通过迭代器);在你的情况下,它只是从向量中删除sizeof(somethingParams)个字节/ char,只要它包含足够的元素,否则可能会出现分段错误。

    查看下面的结果,这简直是胡说八道。

    char t[] = {'a', 'b', 'c', '\0', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'};
    vector<char> rcvbuf(t, t + 16);
    
    struct somethingParams {
        char Magic[4] = {'w', 'x', 'y', 'z'};
        int Version{99};
        int MsgID{99};
        int MsgLen{99};
    } mParams;
    
    
    memcpy(&mParams, rcvbuf.data(), sizeof(somethingParams));
    //rcvbuf.erase(rcvbuf.begin(), rcvbuf.begin() + sizeof (somethingParams));
    
    cout << "Magic:   " << mParams.Magic << endl;
    cout << "Version: " << mParams.Version << endl;
    cout << "MsgID:   " << mParams.MsgID << endl;
    cout << "MsgLen:  " << mParams.MsgLen << " bytes" << endl;
    

    结果(int在我的机器上占用4个字节):

    Magic:   abc
    Version: 1734763876
    MsgID:   1802135912
    MsgLen:  1869507948 bytes