Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用std::function作为成员函数,它捕获'this',并在析构函数之后从复制的lambda访问它_C++_Lambda_Temporary Objects - Fatal编程技术网

C++ 使用std::function作为成员函数,它捕获'this',并在析构函数之后从复制的lambda访问它

C++ 使用std::function作为成员函数,它捕获'this',并在析构函数之后从复制的lambda访问它,c++,lambda,temporary-objects,C++,Lambda,Temporary Objects,发布一个代码示例(我认为它是最小的、完整的和可验证的足够了): 为什么??背后是什么 如何修复?(输出100500,而不是-1) 我在询问框中写了一些我自己的理由,但发现它更适合作为答案发布(这会使问题太长)。如果我的答案是错误的,请更正它,欢迎更多的答案啊,它应该责怪临时-Bang(100500)的析构函数,它返回表单GetBang,is,have ,例如: 因为这里是noRVO,所以临时Bang(100500)将首先分配给b,然后被销毁 customoperator()、constr

发布一个代码示例(我认为它是最小的、完整的和可验证的足够了):

  • 为什么??背后是什么
  • 如何修复?(输出
    100500
    ,而不是
    -1

我在
询问框中写了一些我自己的理由,但发现它更适合作为答案发布(这会使问题太长)。如果我的答案是错误的,请更正它,欢迎更多的答案

啊,它应该责怪临时-
Bang(100500)
的析构函数,它返回表单
GetBang
,is,have

  • ,例如:


  • 因为这里是no
    RVO
    ,所以临时
    Bang(100500)
    将首先分配给
    b
    ,然后被销毁

  • custom
    operator()
    constructor
    destructor
    以输出一些信息:


  • 显示:

    • dtor
      将在输出之前被调用,这意味着临时对象已被销毁
    • m_值
      的地址不变
    这两个参数保证我们仍然可以从
    b
    m\u foo()
    访问临时变量的
    m\u值

    访问已销毁的对象时,应该是未定义的行为,但不需要警告和错误

    更新 要解决此问题,有两种解决方案:

  • 正如前面指出的,使用初始值设定项捕获:
    [bang=*this]
    。这需要c++14
  • 通过复制捕获当前对象更简单的方法:
    [*this]
    。这需要c++17
    您可能希望通过值
    *将当前对象传递给lambda,以便在复制assign
    Bang
    时可以存储和复制该对象。传递指针
    将存储并复制指向临时对象的指针,该临时对象在复制assign
    Bang
    时已被销毁

    这是应该做到的:

    #include <iostream>
    #include <functional>
    
    class Bang
    {
    public:
        Bang(int i = 0) : m_val(i)
        {
            m_foo = [bang = *this] { std::cout << bang.m_val << std::endl; };
        }
    
        ~Bang()
        {
            m_val = -1;
        }
    
        void Foo()
        {
            m_foo();
        }
    private:
        int m_val;
        std::function<void()> m_foo;
    };
    
    Bang GetBang()
    {
        return Bang(100500);
    }
    
    int main()
    {
        Bang b;
        b = GetBang();
        b.Foo();
        return 0;
    }
    
    #包括
    #包括
    课堂爆炸
    {
    公众:
    Bang(int i=0):m_val(i)
    {
    m_foo=[bang=*this]{std::cout
    
    -1
    
        class Lambda
        {
        public:
            void operator()() const
            {
                //output
            }
    
        private:
            Bang& bang;
    
        public:
            Lambda(Bang& bang) : bang{bang}
            {
            }
    
        } lambda{*this};
        ...
        m_foo = lambda;
    
    #include <iostream>
    #include <functional>
    
    using namespace std;
    
    class Bang
    {
    public:
        Bang(int i = 0) : m_val(i)
        {
    
            std::cout << "Bang(int i = 0) m_val address is " << &m_val << '\n';
            class Lambda
            {
            public:
                void operator()() const
                {
    
                    std::cout << "operator() m_val address is " << &bang.m_val << '\n';
                    std::cout << bang.m_val << std::endl;
                }
    
            private:
                Bang &bang;
    
            public:
                Lambda(Bang &bang) : bang{bang}
                {
                }
    
            } lambda{*this};
            m_foo = lambda;
    
        }
    
        ~Bang()
        {
            std::cout << "~Bang()\n";
            m_val = -1;
        }
    
        void Foo()
        {
            m_foo();
        }
    
    private:
        int m_val;
        std::function<void()> m_foo;
    };
    
    Bang GetBang()
    {
        return Bang(100500);
    }
    
    int main()
    {
        Bang b;
        b = GetBang();
        b.Foo();
        return 0;
    }
    
    Bang(int i = 0) m_val address is 0x7ffd202c48b0
    Bang(int i = 0) m_val address is 0x7ffd202c48e0
    ~Bang()
    operator() m_val address is 0x7ffd202c48e0
    -1
    ~Bang()
    
    #include <iostream>
    #include <functional>
    
    class Bang
    {
    public:
        Bang(int i = 0) : m_val(i)
        {
            m_foo = [bang = *this] { std::cout << bang.m_val << std::endl; };
        }
    
        ~Bang()
        {
            m_val = -1;
        }
    
        void Foo()
        {
            m_foo();
        }
    private:
        int m_val;
        std::function<void()> m_foo;
    };
    
    Bang GetBang()
    {
        return Bang(100500);
    }
    
    int main()
    {
        Bang b;
        b = GetBang();
        b.Foo();
        return 0;
    }