提问者:小点点

C++何时/为什么由值构造/销毁捕获变量


我很难理解这里对C(常量C&;)的调用是怎么回事 和~C()

因此,我创建了一个lambda,它通过值捕获,然后返回它。 据我所知,每个返回的lambda都有自己的上下文(跟踪与声明一致)。

然而,根据stroustrup对lambda作为函数对象快捷方式的描述(在C++第四版的11.4.1中),我希望只对捕获的变量进行一次复制,而事实似乎并非如此。

这是我的代码

//g++  5.4.0
#include <functional>
#include <iostream>
using namespace std;

class C{
    float f; 
  public:
    C(float f): f(f){ cout << "#build C(" << f << ")\n"; }
    C(const C& c): f(c.f+0.1){ cout << "#copy C(" << f << ")\n"; }
    ~C(){ cout << "#destroy C(" << f << ")\n"; }
    void display() const { cout << "this is C(" << f << ")\n"; }
};

std::function<void(void)> make_lambda_val(int i){
    C c{i};
    return [=] () -> void { c.display(); } ;
}

int main(){
    cout << "/**trace\n\n";
    cout << "---  ??  ---\n";
    {
        auto l0 = make_lambda_val(0);
        auto l1 = make_lambda_val(1);
        auto l2 = make_lambda_val(2);
        cout << "ready\n";
        l0();
        l1();
        l2();
    }
    cout << "\n*/\n";
}

以及对应的痕迹:(附我的评论)

/**trace

---  ??  ---
#build C(0)
#copy C(0.1)     <<--|  2 copies ??
#copy C(0.2)     <<--|  
#destroy C(0.1)  <----  one of which is already discarded ?
#destroy C(0)
#build C(1)
#copy C(1.1)
#copy C(1.2)
#destroy C(1.1)
#destroy C(1)
#build C(2)
#copy C(2.1)
#copy C(2.2)
#destroy C(2.1)
#destroy C(2)
ready
this is C(0.2)   <---- the second copy is kept ?
this is C(1.2)
this is C(2.2)
#destroy C(2.2)
#destroy C(1.2)
#destroy C(0.2)

*/

共2个答案

匿名用户

我希望只对捕获的变量进行一次复制

并且捕获的变量确实被复制了一次。 也就是说,它只是复制操作中的源一次。

std::function不是lambda。 它的初始化涉及复制可调用对象。 因此,当lambda被复制到std::function中时,它按值保存的变量也被复制。 当函数返回时,lambda临时程序将被销毁。 您看到的是您创建的lambda内部变量的破坏。

匿名用户

来自lambda生成函数make_lambda_val(int)std::function返回类型为该分析添加了额外的复制复杂性层,这解释了您在跟踪输出中标记的额外复制。

为了简化,请用以下lambda make lambda对象(作用域在main())完全替换make_lambda_val(int)函数,从而替换额外的std::function层:

auto make_lambda_val = [](int i){
    C c(i);
    return [=] () -> void { c.display(); };
};

在这种情况下,跟踪输出看起来与预期的一样:

/**trace

---  ??  ---
#build C(0)
#copy C(0.1)
#destroy C(0)
#build C(1)
#copy C(1.1)
#destroy C(1)
#build C(2)
#copy C(2.1)
#destroy C(2)
ready
this is C(0.1)
this is C(1.1)
this is C(2.1)
#destroy C(2.1)
#destroy C(1.1)
#destroy C(0.1)

*/

相关问题


MySQL Query : SELECT * FROM v9_ask_question WHERE 1=1 AND question regexp '(c++|值|构造|销毁|捕获|变量)' ORDER BY qid DESC LIMIT 20
MySQL Error : Got error 'repetition-operator operand invalid' from regexp
MySQL Errno : 1139
Message : Got error 'repetition-operator operand invalid' from regexp
Need Help?