std :: launder의 목적은 무엇입니까?


242

P0137 은 함수 템플릿을 소개하고 std::launder공용체, 수명 및 포인터에 관한 섹션에서 표준을 많이, 많이 변경합니다.

이 백서가 해결하는 문제는 무엇입니까? 내가 알아야 할 언어에 어떤 변화가 있습니까? 그리고 우리는 무엇을하고 launder있습니까?


2
당신은 종이 자체에 대해 또는 std::launder있습니까? std::launder"const 또는 reference 멤버가 있더라도 동일한 유형의 기존 오브젝트가 차지하는 스토리지에서 작성된 오브젝트에 대한 포인터를 얻는 데 사용됩니다."
txtechhelp

7
주제에 유용한 링크 . 또한이 질문 stackoverflow.com/questions/27003727/…
Paul Rooney

이는 현재 버전 15.7.0에서 VC2017에서 출시되었습니다
데미안

std에 따르면 포인터는 사소한 유형이므로 세탁은 아무것도하지 않습니다. ;)
curiousguy

답변:


250

std::launder당신이 그것이 무엇인지 알고있는 경우에만 적절하게 이름이 지정됩니다. 메모리 세탁을 수행 합니다 .

논문의 예를 고려하십시오.

struct X { const int n; };
union U { X x; float f; };
...

U u = {{ 1 }};

이 문은 집계 초기화를 수행하여 Uwith 의 첫 번째 멤버를 초기화합니다 {1}.

때문에 nA는 const변수, 컴파일러는 그 가정에 무료로 u.x.n하여야한다 항상 일을합니다.

이렇게하면 어떻게됩니까?

X *p = new (&u.x) X {2};

X사소한 것이기 때문에 새로운 객체를 만들기 전에 이전 객체를 파괴 할 필요가 없으므로 완벽하게 법적인 코드입니다. 새로운 객체는n 멤버는 2입니다.

말해봐 ... 무슨 일이 u.x.n돌아 올까?

명백한 대답은 2입니다. 그러나 컴파일러는 진정한 const변수 (단지 const&, 그러나 선언 된 객체 변수 const) 가 절대 변하지 않는다고 가정 할 수 있기 때문에 잘못 되었습니다 . 그러나 우리는 방금 변경했습니다.

[basic.life] / 8 은 변수 / 포인터 / 이전 객체에 대한 참조를 통해 새로 생성 된 객체에 액세스 할 수있는 상황을 설명합니다. 그리고 const회원을 갖는 것은 실격 요소 중 하나입니다.

그럼 ... 어떻게 이야기 할 수 u.x.n있을까요?

우리는 기억을 세탁해야합니다.

assert(*std::launder(&u.x.n) == 2); //Will be true.

자금 세탁은 사람들이 돈을 얻은 곳을 추적하지 못하도록하는 데 사용됩니다. 메모리 세탁은 컴파일러 가 객체를 가져온 위치를 추적 하지 못하도록하여 더 이상 적용되지 않는 최적화를 피하도록합니다.

실격 요인 중 하나는 개체 유형을 변경하는 경우입니다. std::launder여기에도 도움이 될 수 있습니다.

aligned_storage<sizeof(int), alignof(int)>::type data;
new(&data) int;
int *p = std::launder(reinterpret_cast<int*>(&data));

[basic.life] / 8 은 이전 오브젝트의 스토리지에 새 오브젝트를 할당하면 이전 오브젝트에 대한 포인터를 통해 새 오브젝트에 액세스 할 수 없음을 알려줍니다. launder우리는 그것을 회피 할 수 있습니다.


34
그래서 내 tl; dr가 정확합니다 : "세탁은 기본적으로 비 UB 유형의 가지 치기를위한 것입니까?"
druckermanly

13
이것이 사실 인 이유를 설명해 주시겠습니까? " 변수 nconst변수 이기 때문에 컴파일러는 u.x.n항상 1 이라고 가정 할 수 있습니다." 표준 어디에서 그렇게 말합니까? 나는 당신이 지적한 바로 그 문제가 처음에는 그것이 거짓이라는 것을 암시하는 것처럼 보이기 때문에 묻습니다. as-if 규칙에서만 적용되어야하며 여기서 실패합니다. 내가 무엇을 놓치고 있습니까?
user541686

10
@Mehrdad [basic.life] / 8 : "" , [...] 원본 객체가 차지한 저장 위치에 새로운 객체가 생성되면 [...] 원래 객체의 이름이 자동으로 새로운 객체를 참조합니다 [...] if : [...] 형식 [...]에 형식이 한정된 비 정적 데이터 멤버 나 참조 형식 [...] "이 포함되어 있지 않습니다.
ecatmur

14
@ 배리 매우; 주소에 ptr표시된 T 유형의 객체가없는 경우 launder사전 조건 을 위반 하므로 결과에 대해 이야기 할 필요가 없습니다.
TC

17
@NicolBolas 하나는 슈퍼 캣이 다른 타사 언어 사용자의 답변을 끝없이 요구하는 것만 큼위원회를 로비하는 것만 희망 할 수 있습니다. 또한 우수한 최적화 컴파일러는 어쨌든memcpy 지원되는 (즉, lax alignment) 플랫폼에서 올바른 해석을 올바른 솔루션으로 최적화합니다 .
underscore_d
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.