루프 내에서 로컬 객체의 소멸자가 다음 반복 전에 호출되도록 보장됩니까?


11

루프가 있고이 루프 내부에 새 스택 변수를 만들면 (힙에 할당하지 않고 루프 본문 내부에 선언 된 변수를 유지하지 않음), 다음 반복이 시작되기 전에이 객체의 소멸자가 호출 될 수 있습니다. 컴파일러에 의해 루프 언 롤링이 그것에 대해 뭔가를 변경 하시겠습니까?


1
루프 언 롤링 자체 는 실행 순서를 변경하지 않습니다. 그러나 루프 병렬화 가이를 수행 할 수 있습니다.
Adrian Mole

답변:


8

보낸 사람 n4800:

6.3.3 블록 범위 :

블록 (8.3)에 선언 된 이름은 해당 블록의 로컬 이름입니다. 블록 범위가 있습니다. 잠재적 인 범위는 선언 지점 (6.3.2)에서 시작하여 블록 끝에서 끝납니다. 블록 범위에서 선언 된 변수는 로컬 변수입니다.

§10.3.6 소멸자 :

객체가 생성 된 블록이 종료되면 소멸자가 암시 적으로 [...] 호출됩니다 (8.7).

§4.1.1 초록 머신 :

이 규정은“만약”규칙이라고도하며, 그 결과는 관찰 가능한 행동에서 결정될 수있는 한 , 요구 사항이 준수 된 것처럼 결과가이 문서의 요구 사항을 자유롭게 무시할 수 있기 때문 입니다. 프로그램 .

[엠파 시스 광산]

예. 변수는 루프의 끝 (블록)에서 범위를 벗어나므로 프로그램의 동작을 관찰하는 사람이 말할 수 있는 한 소멸자가 호출 됩니다 .


1
소멸자가 호출되는 시점에 대해서는 아무것도 없습니다.
stark

2
@stark 그들이 할 수있는 것은 as-if 규칙입니다. 표준은 추상 기계의 동작 만 지정합니다. 여기에 대한 답변으로 모든 세부 사항을 조사 해야하는지 확실하지 않습니다.
Max Langhof

2
@stark 이것은 질문과 관련이없는 IMO입니다. 당신은 또한 소멸자가 인라인 될 수 있으며, 따라서 전혀 식하지 않을 수 있다고 말할 수 있습니다 call. 또는 그들이 (있는 그대로) 아무 것도 효과적으로하지 않으면, 그러한 소멸자를위한 어셈블리가 없을 수도 있습니다.
Daniel Langr


2
@stark 어디에 정의되어 무엇 ? 이 토론은 질문에 대한 주제가 아닙니다. 이 문제에 대해 다른 별도의 질문을 할 수 있습니다.
Daniel Langr

8

예. 변수를 선언하는 "블록"을 고려할 때 (예 : 괄호 쌍 사이) 시각화하기가 더 쉽습니다. 루프 자체는 블록이며 다음 반복 전에 닫기 브래킷에 도달하면 루프에 선언 된 자동 저장 변수의 모든 소멸자가 호출됩니다.

컴파일러에 의한 루프 언 롤링이 그것에 대해 무언가를 바꿀 수 있습니까?

일반적으로 컴파일러는 최적화하는 작업에 관계없이 프로그램의 동작을 보장해야하기 때문에 컴파일러가 최적화 할 대상을 생각하지 않습니다. 이 경우 루프 언 롤링은 이러한 효과가 발생하더라도 아무 것도 변경하지 않습니다.


2
경험 법칙으로 +1, 코드를 작성할 때 컴파일러 내부에 대해 걱정할 필요가 없습니다. 내 대답에 같은 정신으로 무언가를 추가하려고했지만 이제는 이미 존재합니다
idclev 463035818

복사 제거와 RVO가 프로그램 동작을 바꾸지 않습니까?
Jean-Baptiste Yunès

@ Jean-BaptisteYunès 그러나 잠재적으로 표준에 따라 허용 할 수도 있습니다.[class.copy.elision]
ChrisMM

괄호 쌍만이 아닙니다 . 당신은 쓸 수 for(...) X x{};x개체 +는 각각의 반복에서 파괴 구축 할 것입니다. 라이브 데모 . 관련 표준 섹션은 stmt.iter / 2 입니다.
Daniel Langr

당 §9.5.2 @DanielsaysreinstateMonica 바와 같이 [stmt.iter]이 (강조 광산) 순수 등가의 "반복 문에서 하위 문 단일 문장이 아닌 화합물 문 경우 가 함유 화합물 문으로 재기록 된 것과 같다 원래 진술. ". 본질적으로 하나의 문장에 중괄호가 있거나없는 것은 정확히 동일한 것을 의미하며 중괄호는 암시 적입니다. 명확성을 위해 생략했습니다.
JBL

2

소멸자는 모든 반복마다 호출됩니다. 따라서 어떤 경우 에는 루프 대신 루프 외부 에서 변수를 선언하는 것이 더 빠릅니다 . 다음과 같은 경우를 가정하십시오.

std::string temp;
for(int i = 0; i < 10; ++i){
    temp = arr[i];
    doSomething(temp);
}

루프를 사용할 때 소멸자가 호출되지 않습니다. 그냥 무시 temp합니다.

그러나 std::string temp = arr[i]생성자 를 사용 하면 각 반복마다 소멸자가 호출됩니다. 루프가 매우 자주 실행되는 경우 비트 런타임이 추가된다고 생각합니다.


소멸자가 호출되는지 여부는 성능의 문제가 아닙니다. RAII 타입을 가지고 있다면, 매번 반복 할 때마다 소멸자가 호출
되기를 원합니다

확실하지 않습니다. temp가 새로운 값으로 다시 할당 될 때 내용 'temp'의 소멸자가 이전 반복에서 보유하고 있지 않습니까?
user1282931

나는 100 % 확실하지 않다. 당신이 뭔가를 발견하면 내 대답을 수정하십시오. :)
Julian Schnabel


0

물론 dtor는 반복이 끝날 때 호출되며 루프 언 롤링은 의미가 의심스러운 객체 생성을 제거 할 수있는 일종의 RVO 등을 제외하고 다른 최적화 (프로그램 최적화는 프로그램 동작을 수정해서는 안 됨)와 같이이 동작을 수정해서는 안됩니다. .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.