std::迭代器、指针和 VC++ 警告 C4996
std::iterator, pointers and VC++ warning C4996
int *arr = (int*) malloc(100*sizeof(int));
int *arr_copy = (int*) malloc(100*sizeof(int));
srand(123456789L);
for( int i = 0; i < 100; i++) {
arr[i] = rand();
arr_copy[i] = arr[i];
}
// ------ do stuff with arr ------
// reset arr...
std::copy(arr_copy, arr_copy+100, arr);
在编译时,我收到以下警告std::copy()
:
c:program files (x86)microsoft visual studio 10.0vcincludexutility(2227):
warning C4996: 'std::_Copy_impl': Function call with parameters that may be
unsafe - this call relies on the caller to check that the passed values are
correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See
documentation on how to use Visual C++ 'Checked Iterators'
我知道如何禁用/忽略警告,但是是否有一个简单的单行解决方案可以从未经检查的指针中制作"已检查的迭代器"?像这样的东西(我知道cout不是像int*那样未经检查的指针,而只是例如(:
ostream_iterator<int> out(cout," ");
std::copy(arr_copy, arr_copy+numElements, out);
我不想写一个全新的专业class my_int_arr_output_iterator : iterator...
.但是我可以使用现有的迭代器之一吗?
---编辑---
由于我使用 c-style-array 和 malloc 而不是 STL 容器有很多问题,我只想说我正在编写一个小程序来测试不同排序算法的性能和内存使用情况。您在上面看到的代码片段是特定于问题的专用版本(原始代码是具有多种方法的模板类,针对不同类型的数组中不同数量的元素测试一种算法(。
换句话说,我确实知道如何使用 STL 容器(vector(及其迭代器(vector::begin/end(来做到这一点。我不知道的是我问的。
不过谢谢,如果不是我,希望其他人会从答案中受益。
您正在寻找的直接答案是 stdext::checked_array_iterator。这可用于将指针及其长度包装到 MSVC checked_iterator中。
std::copy(arr_copy, arr_copy+100, stdext::checked_array_iterator<int*>(arr, 100) );
它们还提供 stdext::checked_iterator,可以包装未经检查的容器。
这是一个"母亲,我可以"的警告:代码是正确的,但库编写者认为你不够聪明,无法处理它。关闭愚蠢的警告。
这是一个:
std::vector<int> arr(100);
std::vector<int> arr_copy(100);
srand(123456789L);
for( int i = 0; i < 100; i++) {
arr[i] = rand();
arr_copy[i] = arr[i];
}
//do stuff
std::copy(arr_copy.begin(), arr_copy.end(), arr.begin());
此问题的便携式解决方案有限。它可以在 boost::filter_iterator 适配器的帮助下完成。
有两个限制:
- 迭代器是双向的,没有随机访问。
it++
和it--
有效,但it+=10
不起作用。 -
it=end(); int val = *it;
未选中,会将垃圾分配给 val。它仅适用于超过最后一个元素的元素。将检查其他迭代器值。为了解决此限制,我总是在使用迭代器的值后推进迭代器。因此,在消耗最后一个值后,它将指向 end((。然后it=end()-1; int val1 = *it++; int val2 = *it++; // segfault or failing assert on this line
.以太方式的错误不会被忽视。
解决方案:
filter_iterator使用用户定义的谓词来控制跳过哪些元素。我们可以定义我们的谓词,它不会跳过元素,但它会断言迭代器是否在调试模式下超出范围。不会对性能造成任何影响,因为在发布模式下,谓词只会返回 true,并且编译器会将其简化。下面是代码:
// only header is required
#include "boost/iterator/filter_iterator.hpp"
// ...
const int arr[] = {1, 2, 3, 4, 5};
const int length = sizeof(arr)/sizeof(int);
const int *begin = arr;
const int *end = arr + length;
auto range_check = [begin, end](const int &t)
{
assert(&t >= begin && &t < end );
return true;
};
typedef boost::filter_iterator<decltype(range_check), const int *> CheckedIt;
std::vector<int> buffer;
std::back_insert_iterator<std::vector<int>> target_it(buffer);
std::copy(CheckedIt(range_check, begin, end), CheckedIt(range_check, end, end), target_it);
for(auto c : buffer)
std::cout << c << std::endl;
auto it = CheckedIt(range_check, begin, end);
it--; // assertion fails
auto it_end = CheckedIt(range_check, end-1, end);
it ++;
std::cout << *it; // garbage out
it ++; // assertion fails.
为了便于移植,你可以使用
template <class T>
T* cloneArray(T *a, int length) {
T *b = new T[length];
for (int i = 0; i < length; i++) b[i] = a[i];
return b;
}
您可以调整它以更改将一个数组复制到另一个数组的行为。
- 警告处理为错误这里有什么问题
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- cppcheck在const std::string[]上引发警告
- GCC对可能有效的代码抛出init list生存期警告
- 如何在BST的这个简单递归实现中消除警告
- 关于std::move的使用,是否有编译警告
- g++ 在某个类成员未初始化时不发出警告
- 参考资源文件VC++中的$(SolutionDir)
- VC++本机单元测试,找不到调试符号
- 如何处理来自核心指南检查器的关于gsl::at的静态分析警告
- 使用typeid警告未使用的变量
- 示例C++项目编译中的警告
- 警告:在函数返回类型 [-Wignore 限定符] 时忽略类型限定符
- std::迭代器、指针和 VC++ 警告 C4996
- VC++ 警告 C4356:无法通过派生类初始化静态数据成员
- 钻石继承方案在 G++ 中编译良好,但在 VC++/Eclipse 中产生警告/错误
- 为什么VC C4244警告(可能丢失数据)专门处理'int'?
- 在VC++中查找引起警告4503的代码
- VC 是否符合警告 C4407 的标准
- 关于 VC++ 和 Sun Studio 中的字段初始化顺序、签名比较和未使用的变量的警告