루틴이 (N)RVO를 활용하고 있는지 어떻게 확인할 수 있나요?
-
09-12-2019 - |
문제
나는 가능할 때마다 내 루틴이 (N)RVO를 활용하고 있는지 확인하고 싶습니다.결과 디스어셈블리를 분석하는 것 외에 루틴이 (N)RVO로 컴파일되고 있는지 확인하거나 확인할 수 있는 방법이 있습니까?현재 저는 주로 MSVC와 GCC에 관심이 있습니다.
해결책
아니 정말.
그러나 코드를 작성할 때 지침을 따를 수 있습니다.
명명되지 않은 반환 값 최적화
이는 디버그 모드에서도 임시 항목을 반환할 때마다 거의 트리거됩니다.
return MyObject(....);
명명된 반환 값 최적화
이는 함수가 항상 동일한 임시 개체를 반환할 때마다 거의 트리거됩니다.
MyObject func() {
MyObject result;
if (...) { return result; }
result.push(0);
return result;
}
이를 혼합할 수 있지만 이 경우 컴파일러가 RVO를 적용하는 것이 거의 불가능해집니다.
MyObject func() {
MyObject result;
if (...) { return MyObject(...); }
return result;
}
여기서 한 수익은 RVO의 혜택을 받고 다른 수익은 그렇지 않을 가능성이 높습니다.추측에 따라 생성하면 막힐 수 있으므로 첫 번째 최적화에 베팅하겠습니다. result
반환 슬롯에 갑자기 가져 가야합니다 if
나뭇가지.단순히 명령문의 순서를 변경하면 작동합니다.
MyObject func() {
if (...) { return MyObject(...); }
MyObject result;
return result;
}
따라서 NRVO의 경험 법칙은 다음과 같습니다. return
선언 사이의 진술 result
그리고 return result;
이외의 것을 반환하는 문 result
그 자체.
이것을 따르면, 당신에게 유리한 확률이 쌓이게 됩니다.그리고 그것은 단지 코드 검토의 문제일 뿐입니다.
또한 변수가 실제로 필요하다는 것을 알기 전에는 변수를 선언하지 않으므로 코드를 더 쉽게 읽을 수 있습니다.
다른 팁
디버그 메소드를 소멸자에 추가 할 수 있습니다.
struct A
{
~A() { cout << "destructor called"; }
};
A foo()
{
A a;
return a;
}
.
소멸자가 호출되면 RVO가 적용되지 않을 것입니다.
내가 생각할 수있는 가능한 방법은 다음과 같습니다.
-
클래스를 통해 생성 된 인스턴스의 수를 추적하는 클래스 내에서 참조 카운트 메커니즘을 구현하는 것은
shared_ptr
와 매우 흡사합니다.이 방법으로 클래스의 추가 복사본을 탐지하여 생성되고 제거됩니다.사본 엘리망이 일어나지 않아. -
복사 엘리전이 발생하지 않는 경우 복사 생성자와 소멸자에 디버그 트레이스를 넣을 수 있습니다. 연속적인 복사본 생성자 및 소멸자 디버그 트레이스를 많이 볼 수 있습니다.