11
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.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'

警告を無効化/無視する方法は知っていますが、チェックされていないポインターから「チェックされたイテレーター」を作成するための簡単なワンライナーソリューションはありますか?次のようなもの(coutはint *のようなチェックされていないポインタではなく、たとえば):

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

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

まったく新しい専門を書きたくありませんclass my_int_arr_output_iterator : iterator...。しかし、既存のイテレータの1つを使用できますか?

- -編集 - -

STLコンテナの代わりにc-style-arraysとmallocを使用することについては多くの質問があるので、さまざまなソートアルゴリズムのパフォーマンスとメモリ使用量をテストするための小さなプログラムを作成しているとだけ言っておきます。上記のコードスニペットは、問題に固有の特殊なバージョンです(元のコードは、複数のメソッドを持つテンプレートクラスであり、さまざまなタイプの配列内のさまざまな数の要素に対して1つのアルゴリズムをテストします)。

言い換えれば、STLコンテナー(vector)とそのイテレーター(vector :: begin / end)を使用してこれを行う方法を知っています。私が知らなかったのは私が尋ねたことです。

でもありがとう、うまくいけば、私でなければ誰か他の人が答えから利益を得るでしょう。

4

5 に答える 5

17

あなたが探している直接の答えはstdext::checked_array_iteratorです。これは、ポインターとその長さをMSVCchecked_iteratorにラップするために使用できます。

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

また、チェックされていないコンテナをラップできるstdext::checked_iteratorも提供します。

于 2012-08-21T21:17:08.920 に答える
8

これは「お母さん、いいですか」という警告です。コードは正しいのですが、ライブラリの作成者は、あなたがそれを処理するほど賢くないと考えています。愚かな警告をオフにします。

于 2012-08-22T00:18:03.503 に答える
6

これが1つです:

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());
于 2012-08-21T20:11:10.857 に答える
1

この問題に対する限定的な移植可能な解決策があります。これは、 boost::filter_iteratorアダプターを使用して実行できます。

次の 2 つの制限があります。

  1. イテレータは、ランダム アクセスのない双方向です。動作しますが、it++動作しません。it--it+=10
  2. 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.
于 2015-05-15T12:51:06.207 に答える
0

移植性のために使用できます

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

これを微調整して、ある配列を別の配列にコピーする動作を変更できます。

于 2013-10-16T10:02:15.110 に答える