简体   繁体   English

std :: iterator,指针和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);

while compiling this I get this warning for std::copy() : 在编译时我得到std::copy()这个警告:

c:\program files (x86)\microsoft visual studio 10.0\vc\include\xutility(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'

I know how to disable/ignore the warning, but is there is a simple one liner solution to make a "checked iterator" out of an unchecked pointer? 我知道如何禁用/忽略警告,但是有一个简单的单行解决方案可以从未经检查的指针中创建一个“已检查的迭代器”吗? Something like (I know cout is not an unchecked pointer like int*, but just eg): 类似的东西(我知道cout不是像int *那样的未经检查的指针,但仅仅是例如):

ostream_iterator<int>  out(cout," ");

std::copy(arr_copy, arr_copy+numElements,  out);

I don't want to write a whole new specialized class my_int_arr_output_iterator : iterator... . 我不想写一个全新的专用class my_int_arr_output_iterator : iterator... But can I use one of the existing iterators? 但是我可以使用现有的迭代器之一吗?

---edit--- - -编辑 - -

As there are many many questions abt my usage of c-style-arrays and malloc instead of STL containers, let me just say that I'm writing a small program to test different sorting algorithms' performance and memory usage. 由于我使用c-style-arrays和malloc而不是STL容器有很多问题,我只想说我正在编写一个小程序来测试不同的排序算法的性能和内存使用情况。 The code snippet you see above is a specialized (original code is template class with multiple methods, testing one algorithm for different number of elements in arrays of different types) version specific to the problem. 您在上面看到的代码片段是专门的(原始代码是具有多种方法的模板类,针对不同类型的数组中的不同数量的元素测试一种算法)特定于该问题的版本。

In other words, I do know how to do this using STL containers (vector) and their iterators (vector::begin/end). 换句话说,我知道如何使用STL容器(向量)及其迭代器(vector :: begin / end)来完成此操作。 What I didn't know is what I asked . 我不知道的是我问的问题

Thanks though, hopefully someone else would benefit from the answers if not me. 谢谢,希望如果不是我,其他人也会从答案中受益。

The direct answer you're looking for is the stdext::checked_array_iterator . 您正在寻找的直接答案是stdext :: checked_array_iterator This can be used to wrap a pointer and it's length into a MSVC checked_iterator. 这可用于将指针及其长度包装到MSVC checked_iterator中。

std::copy(arr_copy, arr_copy+100, stdext::checked_array_iterator<int*>(arr, 100) );

They also provide a stdext::checked_iterator which can wrap a non-checked container. 它们还提供了一个stdext :: checked_iterator ,它可以包装一个未经检查的容器。

This is a "Mother, may I" warning: the code is correct, but the library writer thinks you're not smart enough to handle it. 这是一个“母亲,可能我”警告:代码是正确的,但图书馆作者认为你不够聪明,无法处理它。 Turn off stupid warnings. 关掉愚蠢的警告。

Here's one: 这是一个:

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());

There is a limited portable solution to this problem. 这个问题的便携式解决方案有限。 It can be done with help of boost::filter_iterator adapter. 它可以在boost :: filter_iterator适配器的帮助下完成。

There are two limitations: 有两个限制:

  1. The iterator is bidirectional without random access. 迭代器是双向的,没有随机访问。 it++ and it-- work but it+=10 doesn't. it++it--工作但it+=10没有。
  2. it=end(); int val = *it; is not checked and will assign garbage to val. 未检查并将垃圾分配给val。 It is only for the element past the last. 它只适用于过去的元素。 Other iterator values will be checked. 将检查其他迭代器值。 To workaround this limitation, I would always advance the iterator after using its value. 为了解决这个限制,我总是在使用它的值后推进迭代器。 So after consuming the last value it would point to end(). 因此,在消耗最后一个值之后,它将指向end()。 Then it=end()-1; int val1 = *it++; int val2 = *it++; // segfault or failing assert on this line 然后it=end()-1; int val1 = *it++; int val2 = *it++; // segfault or failing assert on this line it=end()-1; int val1 = *it++; int val2 = *it++; // segfault or failing assert on this line it=end()-1; int val1 = *it++; int val2 = *it++; // segfault or failing assert on this line . it=end()-1; int val1 = *it++; int val2 = *it++; // segfault or failing assert on this line Ether way the error will not go unnoticed. 以太方式错误不会被忽视。

The solution: 解决方案:

filter_iterator uses a user defined predicate to control which elements are skipped. filter_iterator使用用户定义的谓词来控制跳过哪些元素。 We can define our predicate that will not skip elements but it will assert if the iterator is out of range in debug mode. 我们可以定义不跳过元素的谓词,但如果迭代器在调试模式下超出范围,它将断言。 There will be no penalty to performance because when in release mode the predicate will only return true and it will be simplified out by the compiler. 性能不会受到惩罚,因为在发布模式下,谓词只会返回true,编译器会将其简化。 Below is the code: 以下是代码:

// 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.

For portability you could use 为了便于携带,您可以使用

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;
}

You can tweak it to change the behaviour to copy one array to another. 您可以调整它以更改将一个数组复制到另一个数组的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM