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

容器如何处理lambda表达式的参数

  •  1
  • getsoubl  · 技术社区  · 7 年前

    假设代码如下:

    #include <iostream>
    #include <type_traits>
    #include <queue>
    #include <functional>
    
    std::queue<std::function<void()>> funcs;
    
    class A
    {
        public:
          A()
          {
            std::cout << "A constructor" << std::endl;
          }
          void foo(int a)
          {
          }
    };
    
    class ThePool
    {
       public:
        template <typename _Callable, typename Object, typename... _Args>
        void QueueFunction(_Callable __f, Object& obj, _Args... __args)
        {
            funcs.push([__f, &obj, &__args...]() mutable
                {
                    (obj.*__f)(__args...);
                });
        }
    };
    
    int main(int argc, char** argv)
    {
        ThePool t;
        A a;
        int x = 5;
        t.QueueFunction(&A::foo, a, x);
        std::function<void()> func = funcs.back();
        func();
        return 0;
    }
    

    在做一个例子时,我注意到当我将A实例作为引用传递,最后为队列提取函数f并将其称为A的实例时,这是不一样的。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Max Langhof    7 年前

    容器确实可以自由复制其元素。此外, std::function 作为 requirement 存储的函子是 CopyConstructible

    • 如果按值传递对象,实际上不必担心对象的生存期。但是,对对象的副本(或复制的参数)调用成员函数可能不是您想要的。

    • 如果通过(某种形式的)引用传递对象(例如,将它们包装在 std::ref )您永远不会创建对象和参数的副本,但它们可能会在调用排队成员函数之前超出范围。

    目前 在原始代码中,您正在创建 obj 在兰姆达( 目标 是一个 Obj& 目标 通过引用( [&obj] ),而不是按值。或者,传递包裹在 标准::参考

    至于参数,它们当前都被复制(都在 QueueFunction

    如果存储引用,则开始时提到的所有复制操作都将只复制引用(而不是对象)。