将指针包装到迭代器中,以便复制到STL容器中
Wrapping pointers into an iterator for copying into an STL container
我有一个指向一些数据的指针,我想把这些数据放入字符串中。我认为使用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++代码再次编译而没有警告。
- 具有 STL 向量类型成员的类的复制内存
- 如何复制存储在数组中的 STL 对象?
- STL向量上出现奇怪的复制构造函数错误
- 是否有任何常规方法可以通知 STL 移动和复制构造函数?
- STL算法函数,如累加,如果传递给它们的函数接受引用,请避免复制
- 从 C 数组进行 STL 阵列,无需复制
- 有没有一种 stl 方法来执行指针向量的深度复制
- 使用具有未定义行为的 (STL) 复制
- STL 复制、配对、矢量和插入器
- 如何使用密钥 2 更新 STL 映射键 1 并将值复制到键 2 中
- 如何使用STL复制地图,过滤和减少C 的行为
- 不必要的对象复制 - C++ STL
- stl 优先级队列中的堆管理是否调用复制构造函数
- 为什么stl::list会复制添加到列表中的元素
- 从函数复制成本返回STL向量
- 复制包含STL成员(如vector)的C++结构的最佳方法是什么
- 如何避免在基于 B 树的类 STL 映射中浪费地复制密钥
- STL 集合的插入方法是否复制传递对象的值?
- STL 关联容器:擦除并取回(不可复制的)元素
- 复制STL:删除元素、用户定义函数作为参数和事件队列