将指针包装到迭代器中,以便复制到STL容器中

Wrapping pointers into an iterator for copying into an STL container

本文关键字:复制 STL 指针 包装 迭代器      更新时间:2023-10-16

我有一个指向一些数据的指针,我想把这些数据放入字符串中。我认为使用std::copy应该是最安全的方法。

然而,在Visual Studio 2010中,我得到一个警告

warning C4996: 'std::_Copy_impl':带有可能不安全参数的函数调用-此调用依赖于调用者检查传递的值是否正确。要禁用此警告,请使用-D_SCL_SECURE_NO_WARNINGS。

当然警告是正确的。在MSDN checked_array_iterator上描述了一些checked_array_iterator对象,它们可以用来包装这样的指针,并使其与STL迭代器兼容。

问题是,这个checked_array_iterator只能作为目标,而不能作为源。

所以当我尝试这样使用它时,应用程序崩溃或无法编译:

char buffer[10] = "Test";
std::string s;
// These are parameters from an external call and only shown here to illustrate the usage.
char *pTargetAdress = &s;
const char *oBegin = buffer;
const char *oEnd = oBegin+sizeof(buffer);
std::string *p = reinterpret_cast<std::string *>(pTargetAdress);
std::copy(oBegin, oEnd, p->begin());   // crash
stdext::checked_array_iterator<const char *>beg(oBegin, oEnd-oBegin);
stdext::checked_array_iterator<const char *>end(oEnd, 0);
std::copy(beg, end, p->begin());   // crash
stdext::checked_array_iterator<const char *>v(oBegin, oEnd-oBegin);
std::copy(v.begin(), v.end(), p->begin());   // doesn't compile

如果有一个可移植的标准方法,我宁愿使用这个而不是依赖于MS扩展。

指针是完美的(随机访问)迭代器。问题在于您将数据复制到坏内存中。p->begin()等于s.begin()等于s.end()指向无效内存。要解决这个问题,可以使用

std::string *p = reinterpret_cast<std::string *>(pTargetAdress);
p->resize(oEnd - oBegin); //resize to make room for the data
std::copy(oBegin, oEnd, p->begin());   // no more crash

或者

#include <iterator>
std::string *p = reinterpret_cast<std::string *>(pTargetAdress);
std::copy(oBegin, oEnd, std::back_inserter(*p));   // copy by appending to the end

或者简单的

std::string *p = reinterpret_cast<std::string *>(pTargetAdress);
*p = std::string(oBegin, oEnd);   // copy by temporary

在您的具体情况下,您可以使用std::string构造函数或assign()方法,请参阅cppreference。

const char* pointer = ...;
std::size_t size = ...;
std::string string(pointer, size);
std::string string(pointer); // if null-terminated

顺便说一下,当从void*转换为T*时,您应该使用static_cast而不是reinterpret_cast

一般

:

如果有一个可移植的标准方法,我宁愿使用这个而不是依赖于MS扩展。

这是Visual Studio 2015中最烦人的警告之一。虽然它的消息为真,但对于每个在原始指针上使用std::copy()的人来说,这应该是显而易见的。建议使用checked_array_iterator的解决方案不仅完全过度设计了一个简单的问题,而且还引入了非标准类,从而使您的代码不可移植。

如果我是你,我会定义_SCL_SECURE_NO_WARNINGS,使完全有效的c++代码再次编译而没有警告。