2010-11-23 4 views
45

가능한 중복 :
Is there a performance difference between i++ and ++i in C++?++ i 또는 i ++ in for 루프 ??

어떤 프로그래머가 대신 i++를 작성 루프 정상에 ++i 쓰기 이유가 있나요?

+0

@djacobson : 글쎄, 당신은 YouTube를 검색 할 수 있고, 아마 얼마나 많은 천사가 동시에 핀 머리에 춤을 추는지 알 수 있습니다. 그러나 제가 의미하는 바는, "특별한 주장에 특별한 증거가 필요하다"는 경우, 사전 증분을 선택하는 것은 실질적으로 전혀 이유가 필요하지 않다는 것입니다. 그것은 대체로 비교할 때, 특히 비범 한 것입니다 ... –

+0

이것은 백 번 전에 묻고 대답해야합니다. –

+1

@Martin York : 매우 이상한 것은 사람들이 아직도 귀찮게 대답한다는 것입니다. –

답변

64

정수의 경우 사전 및 사후 증가 사이에는 차이가 없습니다.

i는 비 단순 클래스의 객체 인 경우는, 평가 후의 i++ 수정 반면, 그래서 제조되는 복사본을 요구 객체가 수정되기 때문에 다음 ++i 일반적으로 바람직하고 평가 하였다.

+14

두 번째 단락으로 인해 같은 코드가 정수로 생성 되더라도 모든 유형에 대해 '++ i'를 사용하는 것이 좋습니다. 따라서 모든 유형에 대해이 습관을 사용하는 습관이 있습니다. – SingleNegationElimination

+2

@ 토큰 : 원칙적으로 동의합니다. 그러나'i ++'는 C 코드에서 다소 관용적이다. 정기적으로 두 언어를 사용하면 혼란 스러울 수 있습니다 ... –

+0

여기 내 무지를 실례하지만 이것은 확실히 어리석은 것처럼 들린다. 'i'가 증분 연산자를 오버로드하는 클래스의 인스턴스라고 상상해보십시오. 내가 단순히 포스트 - 인크 리먼 트 (loop control statement가 아닌, 단지''++ '')를하면, 컴파일러는 내가 * 리턴 값을 가지고 * 아무것도하지 않고, 자동적으로'++ i'라고 재 작성하겠습니까? –

0

개인 취향.

일반적으로. 때로는 중요하지만 여기서는 멍청이처럼 보일 수는 없지만 물어 봐야한다면 그렇지 않을 수도 있습니다. 가치

1

없음 컴파일러 소금의 무게 ++

for(int i=0;i<10;++i) 

for(int i=0; i<10; i++) 

사이에 다르게 난을 실행하고 난 같은 비용을 가지고 ++. 유일한 차이점은 ++ i의 반환 값은 i + 1이고 i ++의 반환 값은 i라는 점입니다.

++ i를 선호하는 사람들에게는 개인적인 취향 인 정당한 이유가 없습니다.

편집 : 이것은 다른 모든 게시물에서 말한 것처럼 클래스에 대해서는 잘못된 것입니다. i ++는 클래스 인 경우 사본을 생성합니다.

+1

이것은 int와 같은 인덱스에 대해서는 사실 일 수 있지만 인덱스로 작용할 수있는 반복자 및 기타 객체에 대해서는 일반적으로 사실이 아닙니다. –

+0

나는 ++와 ++를 같은 연산자라고 부르지 않습니까? – rtpg

+1

아니요,'++ i'는'i.operator ++()'를 호출하고'i ++'는'i.operator (int)'를 호출합니다. 구현 세부 정보는 [내 대답] (http://stackoverflow.com/questions/4261708/i-or-i-in-for-loops/4261836#4261836)을 참조하십시오. – fredoverflow

0

postfix를 사용하면 메모리의 더 많은 객체를 인스턴스화합니다. 어떤 사람들은 for 루프에서 접미사 연산자를 사용하는 것이 더 낫다고 말합니다.

6

++i은 사전 증가입니다. i++은 사후 증가입니다.
사후 증가의 단점은 추가 값을 생성한다는 것입니다. 을 수정하는 동안 이전 값의 사본을 반환합니다. i. 따라서 가능하면 피해야합니다.

81

++i 때문에 그 의미를 약간 더 효율적이다

++i; // Fetch i, increment it, and return it 
i++; // Fetch i, copy it, increment i, return copy 

INT 같은 인덱스를 들어, 효율성 이득 (있는 경우) 최소이다. 반복기 및 기타 무거운 객체의 경우 해당 복사본을 피하는 것이 실제 승리가 될 수 있습니다 (특히 루프 본문에 많은 작업이 포함되지 않은 경우).

은 예로서, 임의의 정밀도의 정수를 제공하는 이론상의 BigInteger 클래스를 사용하여 다음 고리를 고려 (따라서 벡터 형 내부의 일종) 나 동작 ++

std::vector<BigInteger> vec; 
for (BigInteger i = 0; i < 99999999L; i++) { 
    vec.push_back(i); 
} 

복사본 구성을 포함한다 (즉,연산자 new, digit by by digit 복사)와 본질적으로 하나 이상의 인덱스 객체 복사본을 만드는 것 이상을 수행하지 않는 루프에 대한 삭제 (연산자 삭제) 근본적으로 접두사가 충분했을 경우 접미사 증분을 사용하여 수행 할 작업을 두 배로 늘릴 수 있습니다 (메모리 조각화 가능성이 높음).

+1

위대하고 간결한 예 –

+3

나는 대답을 upvote하고 싶다. 그렇지만 더 이상 42라고 평가되지 않을 것이다. –

+1

@ KiJéy 지금 다시 돌아올 수있다. (하지만 더 이상 등급이 매겨지지 않을 것입니다 ...) – wizzwizz4

2

성능에 대한 이유가 있습니다. 성능. i ++는 복사본을 생성하고 즉시 폐기하면 낭비가됩니다. 물론, 컴파일러는 i이 프리미티브 인 경우이 복사본을 최적화 할 수 있지만 그렇지 않은 경우에는 복사 할 수 없습니다. 질문 : this을 참조하십시오.

+1

이것은 부 자연스러운 것입니다. 거의 모든 경우에,'++ i'와'i ++'의 성능은 완전히 같습니다. –

+3

@ 존 :별로 솔직하지 않다. iterator 객체의 경우, 컴파일러는 접두사와 후위 증가 사이에 어떤 종류의 동등성을 기대할 이유가 없습니다 (클래스 디자이너는 임의적으로 다른 작업을 수행 할 수 있습니다) - 결과 사본을 후위 양식으로 호출해야합니다. 헤비급 반복기 및 경량 루프의 경우 성능이 크게 떨어질 수 있습니다. 예를 들어 int 또는 std :: vector가 아닌 경우 :: iterator가 아니라 BigInteger 또는 이와 동등한 것입니다. 사본은 불필요한 것이며 피해야합니다. –

+1

@Drew :이 경우 프로그래머는 그것을 (또는 어쨌든) 알게 될 것이고, "부탁해야한다면, 중요하지 않습니다"라는 말을 부인할 것입니다. 문제는 "일반 루프"에 관한 것입니다. 성과는 그 성과와 아무 상관이 없습니다. 개인 스타일에 관한 모든 것. –

4

정수를 사용하는 것이 좋습니다.

루프 변수가 클래스/객체 인 경우 사후 증가 버전에서는 삭제되는 객체의 사본을 만들어야하므로 차이가 발생할 수 있습니다 (프로파일 링만으로 큰 차이가 있는지 만 알 수 있음). .

복사본을 만드는 것이 비용이 많이 드는 작업 인 경우 루프를 거칠 때마다 비용을 지불해야합니다. 이유는 전혀 없습니다.

for 루프에서 항상 ++i을 사용하는 습관을 갖게되면이 특정 상황에서 수행중인 작업이 의미가 있는지 여부를 막을 필요가 없습니다. 당신은 항상 존재합니다.

1

다른 사람들이 이미 언급했듯이 사전 증가는 일반적으로 사용자 정의 유형의 사후 증가보다 빠릅니다. 왜 그런지 이해하려면 두 연산자를 구현하는 전형적인 코드 패턴을보고 : 당신이 볼 수 있듯이

Foo& operator++() 
{ 
    some_member.increase(); 
    return *this; 
} 

Foo operator++(int dummy_parameter_indicating_postfix) 
{ 
    Foo copy(*this); 
    ++(*this); 
    return copy; 
} 

는 접두사 버전은 단순히 객체를 수정하고 참조로 돌려줍니다.

반면에 후치 버전은 실제 증가분이 수행되기 전에 사본을 만들어야 만합니다. 그런 다음 사본은 값에 의해 호출자에게 다시 복사됩니다. 소스 코드에서 접미어 버전에 대한 호출이 포함되어 있기 때문에 접미어 버전이 더 많은 작업을해야한다는 것이 분명합니다. ++(*this);

내장 유형의 경우 값을 버리면 아무런 차이가 없습니다 예를 들어, a = ++i 또는 b = i++과 같이 큰 표현식에 ++i 또는 i++을 삽입하지 않는 한.

+2

"사본을 만들어야합니다"라고 생각하면 조금 과장됩니다. 결과가 사용되지 않고 연산자와 복사 생성자가 둘 다 완전히 인라인 될 수 있다면 반복기에서 일반적으로 그러 하듯이 최적화 프로그램이 부작용없이 완전히 복사 된 사용되지 않은 값을 제거 할 수 있어야합니다. 효과. '++ i'는 최적화가 성공했는지 궁금해하지 않으며, 더 중요한 것은 * 분명히 더 이해하기 쉽다 * ;-) –