添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Is it safe to pass std::function<bool(std::string)> &&callback (i.e. as a rvalue move) and what is the effect?

Ask Question std::function<bool(std::string)> m_callback; void do_work(std::function<bool(std::string)> callback) // <--- this line m_callback = std::bind(callback, std::placeholders::_1); callback("hello world!\n"); // pretty boring class - a cut down of my actual class struct helper worker the_worker; bool work_callback(std::string str) std::cout << str << std::endl; return false; int main() helper the_helper; the_helper.the_worker.do_work( [&](std::string data){ return the_helper.work_callback(data); });

Compiled with: -std=c++11 -O2 -Wall -Wextra -pedantic-errors -O2 main.cpp

I have comment the line in question ( <-- this line - around line 7), where I think it would be more efficient to use: void do_work(std::function<bool(std::string)>&& callback) i.e. using the && move semantic.

I have never really used this, mostly because I still don't quite understand it.

My understanding is this:

void do_work(std::function<bool(std::string)> callback) - will take a copy of the lambda that I pass in (which is an rvalue I think).

void do_work(std::function<bool(std::string)> callback) - will move the lambda that I pass in because it is an rvalue.

My crude idea of an rvalue is any temporary variable.

Questions:

  • What I am not 100% clear about is, is what I wrote correct? and therefore is it safe to use && . Both seem to work.

  • Does this && method also work if instead of passing a lambda like this:

  • the_helper.the_worker.do_work( [&](std::string data){ return the_helper.work_callback(data); });

    we pass in std::bind(...):

    the_worker.do_work(std::bind(&helper::work_callback, the_helper, std::placeholders::_1));

    @Someprogrammerdude I know - you'll have to just forgive this crappy example! (its hard to make a simple example just to show a point without makeing crap code)... but I do want to pass and store the callback in this way (i.e. with lambda or bind). I just really want to focus on the pass type (i.e. by value or by && ). code_fodder Aug 29, 2018 at 10:35

    If the parameter is defined as an rvalue-reference, you must pass a temporary or cast an lvalue to an rvalue, like with std::move() .

    And the semantics of rvalue-references are that the caller should expect the passed argument to be plundered, rendering it valid but arbitrary, meaning mostly useless.

    But the function receiving an rvalue-reference, despite having license to plunder , does not have any obligation to plunder . And if it doesn't explicitly do so, for example by passing that license on, then it doesn't come to pass, and nothing special happens.

    Your code is such a case.

    While I would ban std::bind from my vocabulary, using it or not doesn't actually make any significant difference.

    I am reading and re-reading the words you wrote, but I think I am too simple to get it!. I think I understand what you are saying about the std::move() - this means that if its an lvalue (like an object or such?) then you move it. Could you explain that last part like I am a child, as in: what happens in the two cases in my code (i.e. is it actually moved?). Thanks :) code_fodder Aug 29, 2018 at 10:40 No, it isn't moved, because even though you use rvalue-references at some points, you don't use them anywhere they would cause a change in behaviour, aka cause the object to be moved from. Deduplicator Aug 29, 2018 at 10:42 Out of curiosity, what is your issue with std::bind ? are you referring to both/all usages of it, or just the usage with passing functions (i.e. the second one)? code_fodder Aug 29, 2018 at 10:44 @code_fodder: My issue with std::bind is that a lambda is both cleaner, and sometimes potentially more efficient. Admittedly, std::bind has the Advantage of producing the same type for the same arguments repeatedly, instead of being unique to each case. Deduplicator Aug 29, 2018 at 10:46 Ok thanks, I was just checking there was not somthing explcitly bad about it - your just saying its effectivly obsoleted by lambdas :) code_fodder Aug 29, 2018 at 10:48

    In this case regardless of whether you pass by value or by rval ref a temporary std::function will have to be created, that's because a lambda is not really a std::function. In any case, you should move the std::function before assigning, to avoid making an unnecessary copy.
    I'd recommend passing by value in this case, as this is a bit more flexible, and if you are passing lambdas, then it does not cause any harm, as the std::function will usually be constructed in place (so the temporary will not be moved into the function; this move can, and usually will, be elided).

    Ok, so, in general, passing a lambda by copy is just the easier/flexible method and we don't by using rvalref? code_fodder Aug 29, 2018 at 10:46 You are not passing a lamda here really, you are using it to create a temporary std::function object, which is then passed into the function. so there are a couple of things that can happen here, e.g. the temporary will be created and then moved into the function or the std::function will be created in place. In practice the second one is much more likely, which is the same thing that would happen if you passed by rval ref. paler123 Aug 29, 2018 at 11:24

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question . Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers .