我有一个std::string变量。我需要将一些来自无符号字符数组的字节放入其中。我知道第一个字节和长度。
我可以使用std::string::assign函数。我已经使用过了。
但是我想用memcpy函数以正确的方式解决这个问题。
std::string newString;
memcpy(&newString, &bytes[startIndex], length);
我知道这是错误的。我已经研究了一些使用std :: vector的想法。
请帮助我找到解决这个问题最优雅的方法。
我有一个std::string变量。我需要将一些来自无符号字符数组的字节放入其中。我知道第一个字节和长度。
我可以使用std::string::assign函数。我已经使用过了。
但是我想用memcpy函数以正确的方式解决这个问题。
std::string newString;
memcpy(&newString, &bytes[startIndex], length);
我知道这是错误的。我已经研究了一些使用std :: vector的想法。
请帮助我找到解决这个问题最优雅的方法。
既然我们只是在构造字符串,那么有一个接受两个迭代器的std::string
构造函数:
template< class InputIt >
basic_string( InputIt first, InputIt last,
const Allocator& alloc = Allocator() );
我们可以提供以下内容:
std::string newString(&bytes[startIndex], &bytes[startIndex] + length);
如果我们不是在构建字符串而是给现有字符串赋值,你仍然应该优先使用assign()
。这正是该函数的作用:
oldString.assign(&bytes[startIndex], &bytes[startIndex] + length);
但是如果出于某些原因您真的坚持要使用 memcpy()
,那么您需要确保字符串实际上具有足够的数据可供复制。然后只需使用 &str[0]
作为目标地址进行复制†:
oldString.resize(length); // make sure we have enough space!
memcpy(&oldString[0], &bytes[startIndex], length);
†在 C++11 之前,技术上不能保证字符串在内存中是连续存储的,尽管实际上通常是这样做的。
&bytes[startIndex + length]
与你已有的代码更一致(没有由程序员执行的指针算术运算)。但是还有一个接受const char*
和长度的字符串构造函数:std::string newString(&bytes[startIndex], length);
。 - Ryan Hainingbytes
是unsigned char
,在这种情况下,该构造函数将不适用。至于另一点,则因人而异。 - Barryunsigned
。在这种情况下将其转换为 const char*
似乎是合法的,但也没什么大不了的。 - Ryan Hainingdata()
得到的指针的常量性强制转换出来。std::string newString;
newString.resize(length);
memcpy((char*)newString.data(), &bytes[startIndex], length);
这是一种hack方法,正如你所说的不正确的方式,但由于STL保证std::string
具有连续的存储空间,因此这是可能的:
std::string str(32, '\0');
std::strcpy(const_cast<char*>(str.data()), "REALLY DUDE, IT'S ILLEGAL WAY");
std::memcpy
(我只是使用strcpy
来复制空终止字符串)...str.resize(length);
memcpy(const_cast<char*>(str.data()), bytes + startIndex, length);
resize()
而不是reserve()
!) - Nevermoredata()
返回的内容”实际上并不遵循我不能修改data()
返回的内容。这个问题没有法律解决方案,我指出这是一个黑客技巧。你想看看像&front()
而不是data()
的另一个黑客技巧吗? - Nevermore
assign()
不是“正确的方法”? - Barrychar
是有符号的, 那么从unsigned char
到char
的转换在一些平台上是由实现定义的。使用memcpy
是一种可移植保留位模式的方式。 - Emile Cormier