참조 또는 값으로 shared_ptr을 전달해야합니까? C ++ 11 STL에서) 가져 가면 전달합니까? const

함수가 shared_ptr(부스트 또는 C ++ 11 STL에서) 가져 가면 전달합니까?

  • const 참조로 : void foo(const shared_ptr<T>& p)

  • 또는 값으로 : void foo(shared_ptr<T> p)?

나는 그것이 더 빠를 것이라고 생각하기 때문에 첫 번째 방법을 선호합니다. 그러나 이것이 실제로 가치가 있습니까? 아니면 추가 문제가 있습니까?

선택해야 할 이유를 알려 주시거나 문제가 해결되지 않는 이유를 말씀해주십시오.



답변

이 질문은 C ++ 및 Beyond 2011의 Ask Us Anything 세션에서 Scott, Andrei 및 Herb가 논의하고 답변했습니다 . 4시 34분에서 시계 에 대한 성능 및 정확성 .shared_ptr

곧, 목표가 객체의 소유권을 공유하는 것이 아니라면 (예를 들어, 다른 데이터 구조 또는 다른 스레드간에) 목표를 공유하지 않는 한, 가치를 지나갈 이유가 없습니다 .

위에 링크 된 토크 비디오에서 Scott Meyers가 설명한대로 이동 최적화 할 수 없다면 실제 C ++ 버전과 관련이 있습니다.

이 토론에 대한 주요 업데이트는 GoingNative 2012 컨퍼런스의 대화식 패널 : 문의하십시오! 특히 22:50 부터 시청할 가치가 있습니다.


답변

여기 허브 셔터의 포획

지침 : 소유권 공유 또는 전송과 같은 스마트 포인터 자체를 사용하거나 조작하지 않는 한 스마트 포인터를 함수 매개 변수로 전달하지 마십시오.

지침 : 함수가 값별 shared_ptr 매개 변수를 사용하여 힙 오브젝트의 소유권을 저장하고 공유 할 것이라고 표현하십시오.

지침 : 비 const shared_ptr & 매개 변수 만 사용하여 shared_ptr을 수정하십시오. 사본을 공유하고 소유권을 공유 할 것인지 확실하지 않은 경우에만 const shared_ptr &을 매개 변수로 사용하십시오. 그렇지 않으면 widget *을 대신 사용하십시오 (또는 null을 허용하지 않으면 widget &).


답변

개인적으로 나는 const참조를 사용할 것 입니다. 함수 호출을 위해 참조 카운트를 다시 감소시키기 위해 참조 카운트를 증가시킬 필요는 없습니다.


답변

에 의해 전달 const이 빠르다 참조. 당신이 그것을 저장 해야하는 경우, 예를 들어 일부 컨테이너에 ref. 복사 작업에 의해 카운트가 자동으로 증가합니다.


답변

나는 한 번에, 아래의 코드를 실행 foo복용 shared_ptr에 의해 const&다시 함께 foo을 복용 shared_ptr값.

void foo(const std::shared_ptr<int>& p)
{
    static int x = 0;
    *p = ++x;
}

int main()
{
    auto p = std::make_shared<int>();
    auto start = clock();
    for (int i = 0; i < 10000000; ++i)
    {
        foo(p);
    }    
    std::cout << "Took " << clock() - start << " ms" << std::endl;
}

인텔 코어 2 쿼드 (2.4GHz) 프로세서에서 x86 릴리스 빌드 VS2015 사용

const shared_ptr&     - 10ms  
shared_ptr            - 281ms 

값별 카피 버전은 10 배 느리게 진행되었습니다.
현재 스레드에서 동 기적으로 함수를 호출하는 경우 const&버전을 선호하십시오 .


답변

C ++ 11부터는 생각보다 const & 보다 자주 을 사용해야합니다 .

기본 유형 T가 아닌 std :: shared_ptr을 사용하는 경우 무언가를 수행하려고하기 때문에 그렇게합니다.

당신이 원하는 경우 복사 할 곳,이 사본을 가지고 가고, 표준 : : 오히려 const를하여 복용 및 다음 나중에 복사하는 것보다, 내부 이동에 더 많은 의미가 있습니다. 함수를 호출 할 때 호출자에게 옵션 std :: move_shared_ptr을 차례로 설정하여 증가 및 감소 조작 세트를 저장하기 때문입니다. 아님 즉, 함수의 호출자는 함수를 호출 한 후 std :: shared_ptr이 필요한지 여부와 이동 여부에 따라 결정할 수 있습니다. const &로 전달하면 달성 할 수 없으므로 값으로 가져 오는 것이 좋습니다.

물론, 호출자가 둘 다 그의 shared_ptr을 더 오랫동안 필요로하고 (따라서 std :: move 그것을 할 수 없음) 함수에 일반 사본을 만들고 싶지 않다면 (약한 포인터를 원하거나 때로는 원할 때만) 조건에 따라 복사하려면 const &가 더 좋습니다.

예를 들어,

void enqueue(std::shared<T> t) m_internal_queue.enqueue(std::move(t));

위에

void enqueue(std::shared<T> const& t) m_internal_queue.enqueue(t);

이 경우 항상 내부적으로 사본을 작성하기 때문에


답변

원자 단위 증가 및 감소가있는 shared_copy 복사 작업의 시간 비용을 알지 못하면 CPU 사용 문제가 훨씬 높아졌습니다. 나는 원자 적 증가를 기대하지 않았고 감소시키는 데 많은 비용이 소요될 수 있습니다.

내 테스트 결과에 따라 int32 원자 증가 및 감소는 비 원자 증가 및 감소보다 2 또는 40 배가 걸립니다. Windows 8.1의 3GHz Core i7에서 얻었습니다. 앞의 결과는 경합이 발생하지 않을 때 나옵니다. 후자는 경합 가능성이 높을 때 나타납니다. 원 자성 작업은 마지막 하드웨어 기반 잠금 상태입니다. 잠금은 잠금입니다. 경합이 발생하면 성능이 저하됩니다.

이것을 경험하면서, 나는 항상 byval (shared_ptr)보다 byref (const shared_ptr &)를 사용합니다.