在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;。
感谢。
答案 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
会带来什么样的合理结果。
但也许我可以唤起一些可以帮助你进一步挖掘的想法:
vector
个char
个元素可能被string
个对象取代? string
对象用于在内部保存char
数组。我认为这更多是C ++,但取决于你的要求。memcpy
只是复制内存。我不确定这是不是你想要的;我认为复制后结构包含垃圾。在我看来不可预测。vector
是STL容器),在C ++中执行此操作的标准方法(除上述std::copy
函数外)是迭代元素并复制它们。见下文。最熟悉迭代器:
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