代码之家  ›  专栏  ›  技术社区  ›  code_fodder

传递std::function<bool(std::string)>&&callback(即作为右值移动)安全吗?效果如何?

  •  0
  • code_fodder  · 技术社区  · 6 年前

    给定以下工作代码(主.cpp):

    #include <functional>
    #include <iostream>
    
    struct worker
    {
       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); });
    }
    

    编制单位: -std=c++11 -O2 -Wall -Wextra -pedantic-errors -O2 main.cpp

    我对这句话作了评论( <-- this line void do_work(std::function<bool(std::string)>&& callback) i、 e.使用 && 移动语义。

    我从来没有真正用过这个,主要是因为我还不太明白。

    我的理解是:

    void do_work(std::function<bool(std::string)> callback) -我会拿一份我传递的lambda的副本(我想这是一个右值)。

    void do\u work(std::function<bool(std::string)>回调) -会移动我传入的lambda,因为它是一个r值。

    问题:

    1. && . 两者似乎都有效。

    2. 是这样吗 && 如果不是像这样传递lambda,方法也可以工作:

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

    我们传入std::bind(…):

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

    2 回复  |  直到 6 年前
        1
  •  3
  •   Deduplicator    6 年前

    如果参数定义为rvalue引用,则必须传递临时值或将左值强制转换为rvalue,如 std::move() .

    rvalue引用的语义是,调用者应该期望传递的参数被掠夺,使其有效但武断,这意味着大部分是无用的。

    抢劫许可证 ,没有任何 . 如果它没有明确地这样做,例如通过传递许可证,那么它就不会通过,也不会发生什么特别的事情。

    std::bind 从我的词汇来看,使用与否实际上并没有什么显著的区别。

        2
  •  1
  •   paler123    6 年前

    在这种情况下,不管您是按value还是按rval ref传递,都必须创建一个临时std::函数,这是因为lambda实际上不是std::函数。在任何情况下,都应该在赋值之前移动std::函数,以避免生成不必要的副本。
    在这种情况下,我建议按值传递,因为这有点灵活,如果传递lambda,那么它不会造成任何伤害,因为std::函数通常会在适当的位置构造(因此临时值不会移动到函数中;这种移动可以而且通常会被忽略)。