Programing

const-reference로 std :: function을 전달해야합니까?

crosscheck 2020. 7. 13. 20:35
반응형

const-reference로 std :: function을 전달해야합니까?


내가 필요한 기능이 있다고 가정 해 봅시다 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)의 경우, 우리는 단순히 장기 저장에. (B)의 경우을 복사해야합니다 .movestd::functionstd::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에는 전혀 사용하지 않아야 합니다.

Making the functor type a template parameter permits greater optimization than std::function, including inlining the functor logic. The effect of these optimizations is likely to greatly outweigh the copy-vs-indirection concerns about how to pass std::function.

Faster:

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

As usual in C++11, passing by value/reference/const-reference depends on what you do with your argument. std::function is no different.

Passing by value allows you to move the argument into a variable (typically a member variable of a class):

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

    Object m_o;
};

When you know your function will move its argument, this is the best solution, this way your users can control how they call your function:

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

I believe you already know the semantics of (non)const-references so I won't belabor the point. If you need me to add more explanations about this, just ask and I'll update.

참고URL : https://stackoverflow.com/questions/18365532/should-i-pass-an-stdfunction-by-const-reference

반응형