답변:
내가 선호하는 it - vec.begin()
나빈에 의해 주어진 반대 이유에 대해 정확하게 : 그렇게 하지 않을 당신이 목록에 벡터를 변경하면 컴파일합니다. 반복 할 때마다이 작업을 수행하면 O (n) 알고리즘을 O (n ^ 2) 알고리즘으로 쉽게 전환 할 수 있습니다.
또 다른 옵션은 반복 중에 컨테이너에서 뛰어 다니지 않으면 인덱스를 두 번째 루프 카운터로 유지하는 것입니다.
참고 : it
컨테이너 반복자의 일반 이름입니다 std::container_type::iterator it;
.
it
입니까?
std::container_type::iterator it;
std::list
, 자신의 위치에 의한 요소에 대한 직접 액세스를 제공하지 않습니다 당신이 할 수없는 경우에 그래서 list[5]
, 당신이 할 수 없어야합니다 list.begin() + 5
.
std::distance(vec.begin(), it)
코드를 변경하지 않고 컨테이너를 변경할 수 있기 때문에 선호합니다 . 예를 들어, 랜덤 액세스 반복자를 제공하지 않는 std::list
대신 사용하기로 결정하면 std::vector
코드는 여전히 컴파일됩니다. std :: distance는 반복자 특성에 따라 최적의 방법을 선택하므로 성능 저하가 없습니다.
vec
은 나쁜 소식입니다. 컨테이너 유형을 템플릿 매개 변수로 사용하여 코드를 일반으로 다시 작성한 경우 비 랜덤 액세스 반복자를 처리하는 방법에 대해 이야기 할 수 있어야합니다 (
vec
이 지정된 벡터를 갖는 것도 나쁜 소식입니다.
UncleBens와 Naveen에서 알 수 있듯이 두 가지 이유가 있습니다. 어떤 행동이 "더 나은"행동인지에 따라 달라집니다. 일정한 시간 행동을 보장하고 싶습니까, 아니면 필요할 때 선형 시간으로 넘어 가기를 원하십니까?
it - vec.begin()
일정한 시간 operator -
이 걸리지 만 무작위 액세스 반복자에서만 정의되므로 코드는 목록 반복자와 함께 전혀 컴파일되지 않습니다.
std::distance(vec.begin(), it)
모든 반복자 유형에 대해 작동하지만 임의 액세스 반복자에서 사용되는 경우 일정 시간 동안 만 작동합니다.
어느 쪽도 "더 나은"것이 아닙니다. 필요한 것을하는 것을 사용하십시오.
나는 이것을 좋아한다 : it - vec.begin()
, 나에게 그것은 "처음부터의 거리"를 분명히 나타 내기 때문이다. 반복자를 사용하면 산술 측면에서 생각하는 데 익숙하므로 -
부호가 가장 분명한 표시기입니다.
distance
.
it++
하지 뭔가 std::increment(it)
우리가하지? 덜 명확하지 않습니까?
++
연산자 우리 반복기를 증가 방법으로서 STL 시퀀스의 일부로서 정의된다. std::distance
첫 번째 요소와 마지막 요소 사이의 요소 수를 계산합니다. -
운영자가 일 한다는 사실 은 단지 우연의 일치 일뿐입니다.
이미 제한하는 경우 / A를 사용하여 알고리즘을 하드 코딩 std::vector::iterator
및 std::vector::iterator
만, 정말없이 사용하여 종료됩니다하지 않는 방법. 알고리즘 중 하나를 선택하면 차이가 생길 수있는 시점을 넘어서 알고리즘이 이미 구체화되었습니다. 둘 다 정확히 같은 일을합니다. 그것은 개인적인 취향의 문제 일뿐입니다. 나는 개인적으로 명시 적 뺄셈을 사용합니다.
반면에 알고리즘에서 더 높은 수준의 일반성을 유지하려는 경우, 즉 언젠가 미래에 다른 반복자 유형에 적용될 가능성을 허용하기 위해 최선의 방법은 의도에 달려 있습니다. . 여기에서 사용할 수있는 반복자 유형과 관련하여 얼마나 제한적인지에 따라 다릅니다.
명시 적 뺄셈을 사용하는 경우 알고리즘은 다소 좁은 반복자 클래스 인 임의 액세스 반복자로 제한됩니다. (이것은 지금 당신이 얻는 것입니다 std::vector
)
을 사용 distance
하면 알고리즘이 훨씬 광범위한 반복자 클래스 인 입력 반복자를 지원합니다.
물론, distance
비 랜덤 액세스 반복자에 대한 계산 은 일반적으로 비효율적 인 작업입니다 (반복 액세스 조작의 경우 빼기만큼 효율적 임). 알고리즘 이 효율성에 따라 비 랜덤 액세스 반복자 에 적합한 지 결정하는 것은 사용자의 몫 입니다. 결과적으로 효율성의 손실은 알고리즘을 완전히 쓸모 없게 만드는 지점으로 치명적입니다. 그러면 빼기를 더 잘 사용해야 비효율적 인 사용을 금지하고 사용자가 다른 반복자 유형에 대한 대체 솔루션을 강요해야합니다. 비 랜덤 액세스 반복기의 효율성이 여전히 사용 가능한 범위에있는 경우 랜덤 액세스 반복기 distance
에서 알고리즘이 더 잘 작동한다는 사실을 사용 하고 문서화 해야 합니다.
따르면 http://www.cplusplus.com/reference/std/iterator/distance/ 때문에, vec.begin()
A는 랜덤 액세스 반복자 거리 방법은 사용 -
연산자.
따라서 성능 관점에서 볼 때 대답은 동일하지만 distance()
코드를 읽고 이해해야하는 사람이 있으면 사용하기 가 더 쉽습니다.
나는 -
변형 std::vector
만을 사용한다 -의미가 분명하고 조작의 단순성 (포인터 빼기 이상은 아닙니다)은 구문 ( distance
, 다른 한편으로는 피타고라스와 같은 소리 )으로 표현됩니다 먼저 읽지 않습니까?). UncleBen이 지적했듯이 실수로로 변경되면 -
정적 어설 션으로도 작동 vector
합니다 list
.
또한 나는 그것이 훨씬 흔하다고 생각합니다-그것을 증명할 숫자가 없습니다. 마스터 논증 :it - vec.begin()
소스 코드가 짧아 타이핑 작업이 적고 공간이 절약됩니다. 귀하의 질문에 대한 정답이 미각의 문제로 귀결된다는 것이 명백하기 때문에, 이것은 또한 유효한 주장 일 수 있습니다 .
다음은 인덱스와 함께 "all"어커런스를 찾는 예제입니다. 이것이 도움이 될 것이라고 생각했습니다.
void _find_all_test()
{
vector<int> ints;
int val;
while(cin >> val) ints.push_back(val);
vector<int>::iterator it;
it = ints.begin();
int count = ints.size();
do
{
it = find(it,ints.end(), 10);//assuming 10 as search element
cout << *it << " found at index " << count -(ints.end() - it) << endl;
}while(++it != ints.end());
}