태그 보관물: function

function

const-reference로 std :: function을 전달해야합니까? x(); } x대신 const-reference를 전달해야합니까 ? : void callFunction(const std::function<void()>&

내가 필요한 기능이 있다고 가정 해 봅시다 std::function.

void callFunction(std::function<void()> x)
{
    x();
}

x대신 const-reference를 전달해야합니까 ? :

void callFunction(const std::function<void()>& x)
{
    x();
}

이 질문에 대한 답변은 기능에 따라 어떻게 달라 집니까? 예를 들어 클래스 멤버 함수 또는 생성자를 std::function멤버 변수에 저장하거나 초기화하는 경우입니다.



답변

성능을 원하면 저장하는 경우 값을 기준으로 전달하십시오.

“UI 스레드에서 실행”이라는 기능이 있다고 가정하십시오.

std::future<void> run_in_ui_thread( std::function<void()> )

“ui”스레드에서 일부 코드를 실행 한 다음 future완료되면 신호를 보냅니다 . (UI 스레드가 UI 요소를 엉망으로 만드는 UI 프레임 워크에서 유용합니다)

고려중인 두 가지 서명이 있습니다.

std::future<void> run_in_ui_thread( std::function<void()> ) // (A)
std::future<void> run_in_ui_thread( std::function<void()> const& ) // (B)

이제 다음과 같이 사용할 것입니다.

run_in_ui_thread( [=]{
  // code goes here
} ).wait();

익명 클로저 (람다)를 생성하고 std::function 그것을 닫고, run_in_ui_thread함수에 전달한 다음 메인 스레드에서 실행이 끝날 때까지 기다립니다.

(A)의 경우, std::function는 람다에서 직접 생성 된 다음 run_in_ui_thread. 람다는move 들어가므로 std::function, 어떤 이동 가능한 상태라도 효율적으로 들어간다.

두 번째 경우, 임시 std::function가 생성되고 람다는 move그 다음에 임시로 생성됩니다.std::function 는에서 참조로 사용됩니다 run_in_ui_thread.

지금까지는 두 가지가 동일하게 수행됩니다. 를 제외하고 run_in_ui_thread함수 인수의 사본을 작성하여 ui 스레드로 보내 실행하십시오! (완료되기 전에 반환되므로 참조를 사용할 수는 없습니다). 사례 (A)의 경우, 우리는 단순히movestd::function 장기 저장에. (B)의 경우을 복사해야합니다 std::function.

그 가게는 가치를 더 잘 전달합니다. 의 사본을 저장할 가능성이 있으면 std::function값으로 전달하십시오. 그렇지 않으면, 어느 쪽의 방법은 대략 동등합니다 : 값을 기준으로 한 유일한 단점은 같은 부피가 큰 경우입니다std::function 를 가지고 다른 하위 메소드를 사용한 후에 하나의 하위 메소드를 갖는 경우입니다. 그것을 막는 것은 a move만큼 효율적 const&입니다.

이제 둘 사이에 다른 상태가 있습니다. std::function 있습니다.

std::function상점이 일부 객체를 저장 한다고 가정하십시오 .operator() const 하지만 는mutable 수정하는 데이터 멤버 (무례합니다!).

std::function<> const&경우mutable 수정 된 데이터 멤버는 함수 호출에서 전파됩니다. 이 std::function<>경우에는 그렇지 않습니다.

이것은 비교적 이상한 코너 사례입니다.

std::function무게가 가볍고 저렴하게 움직일 수있는 다른 유형과 같이 취급하려고 합니다. 이동이 저렴하고 복사 비용이 많이들 수 있습니다.


답변

성능이 걱정되고 가상 멤버 함수를 정의하지 않은 경우에는 사용하지 않아야합니다. std::function 에는 전혀 합니다.

functor 유형을 템플릿 매개 변수로 만들면 std::functionfunctor 로직 인라이닝을 포함하여 보다 큰 최적화가 가능 합니다. 이러한 최적화의 효과는 전달 방법에 대한 copy-vs-indirection 문제보다 훨씬 클 것 std::function입니다.

더 빠름 :

template<typename Functor>
void callFunction(Functor&& x)
{
    x();
}

답변

C ++ 11에서와 마찬가지로 value / reference / const-reference로 전달하는 것은 인수로 수행하는 작업에 따라 다릅니다. std::function다르지 않습니다.

값으로 전달 하면 인수를 변수 (일반적으로 클래스의 멤버 변수)로 이동할 수 있습니다.

struct Foo {
    Foo(Object o) : m_o(std::move(o)) {}

    Object m_o;
};

함수가 인수를 옮길 것임을 알면 이것이 최선의 해결책입니다.이 방법으로 사용자는 함수 호출 방법을 제어 할 수 있습니다.

Foo f1{Object()};               // move the temporary, followed by a move in the constructor
Foo f2{some_object};            // copy the object, followed by a move in the constructor
Foo f3{std::move(some_object)}; // move the object, followed by a move in the constructor

나는 당신이 이미 (비) const-references의 의미를 알고 있다고 생각하므로 요점을 다루지 않을 것입니다. 이것에 대해 더 많은 설명을 추가 해야하는 경우 물어보십시오. 업데이트합니다.


답변