이동 조작 (이동 생성자와 같은) std::shared_ptr
은 기본적으로 "스틸 링 포인터" (소스에서 대상으로,보다 정확하게 말하면 전체 상태 제어 블록은 참조 카운트 정보를 포함하여 소스에서 대상으로 "도난")이므로 저렴 합니다. .
대신 원자 참조 카운트 증가 (즉 , 정수 데이터 멤버뿐만 아니라 Windows 호출)의 복사 작업 은 포인터 / 상태를 훔치는 것 보다 비용 이 많이 듭니다 .std::shared_ptr
++RefCount
RefCount
InterlockedIncrement
따라서이 경우의 참조 횟수 역학을 자세히 분석하십시오.
// shared_ptr<CompilerInvocation> sp;
compilerInstance.setInvocation(sp);
값을 전달한 sp
다음 메소드 내에서 사본 을 가져 오면 다음을 수행 CompilerInstance::setInvocation
할 수 있습니다.
- 메소드를 입력 할 때
shared_ptr
매개 변수는 복사 구성됩니다. ref count atomic incremental .
- 메소드 본문 내에서 매개 변수를 데이터 멤버에 복사 합니다
shared_ptr
. ref count atomic incremental .
- 메소드를 종료하면
shared_ptr
매개 변수가 삭제됩니다 (ref count atomic decrement) .
총 3 개의 원자 연산에 대해 2 개의 원자 증분과 1 개의 원자 감소가 있습니다.
대신 Clang의 코드에서 올바르게 수행 된 것처럼 shared_ptr
값으로 매개 변수 를 전달한 다음 std::move
메서드 내부에 매개 변수 를 전달하면
- 메소드를 입력 할 때
shared_ptr
매개 변수는 복사 구성됩니다. ref count atomic incremental .
- 메소드 본문 내에서 데이터 멤버에
std::move
대한 shared_ptr
매개 변수 : 참조 횟수는 변경 되지 않습니다 ! 당신은 포인터 / 상태를 훔치고 있습니다 : 비싼 원자 참조 횟수 작업이 필요하지 않습니다.
- 메소드를 종료하면
shared_ptr
매개 변수가 삭제됩니다. 그러나 2 단계에서 이동 했으므로 shared_ptr
매개 변수가 더 이상 아무것도 가리 키지 않으므로 폐기 할 것이 없습니다. 이 경우에도 원자 감소는 발생하지 않습니다.
결론 :이 경우 하나의 심판 카운트 원자 증분, 즉 하나의 원자 연산 을 얻습니다 .
보시다시피, 이것은 복사 사례에 대해 두 개의 원자 단위 증가와 하나의 원자 감소 (총 세 개의 원자 연산) 보다 훨씬 낫 습니다 .