为什么一个物体被摧毁不止一次? [C ++ 11]

时间:2016-05-13 10:04:53

标签: c++ function c++11 lambda scope

在这个小例子中,一个对象被多次破坏......

输出位于:http://ideone.com/ddJ6Hh

#include <iostream>
#include <string>
#include <memory>
#include <functional>

using namespace std;
struct sA
{
    static int n;
    int id;
    string name;
    sA(string s="default"):id(++n),name(s)  {   cout<<"object '"<<name<<"' created\t  id="<<id<<"\taddr="<<this<<"\tn="<<n<<"\n";   }
    ~sA()   {   cout<<"object '"<<name<<"' destroyed\t  id="<<id<<"\taddr="<<this<<"\tn="<<--n<<"\n";   }

//  sA(const sA& other):id(++n),name(other.name+"_Copy")    {   cout<<"object '"<<name<<"' copied\t  id="<<id<<"\taddr="<<this<<"\tn="<<n<<"\n";    }
    sA operator=(const sA& other)   =delete;
};
int sA::n;




int main()
{
    function<void(void)> vp;

    {
        sA f("1___This Object will die when others need it...");
        sA b("2___This Object will not die ...");
        vp=[&f,b]
        {
            cout<<"Hello\n";
            cout<<b.name<<"||\t addr="<<&b<<"\t|<*>| Stack Data is ok\n";
            cout<<f.name<<"||\t addr="<<&f<<"\t|<*>| Stack Data may not be there\n";
        };
        vp();
        cout<<"********* Block end\n";
    }

    sA k("3__test obj");
    vp();
    return 0;
}

到目前为止,我想出的可能原因是:

1)lambda采用的局部对象的引用超出了范围。[对象&#39; f&#39;]

2)调用默认复制构造函数,旧版本被销毁[对象b]

但这些原因并没有回答以下事实:

1)即使在最内部的块结束之前,两个对象也被破坏了。 [确定了块结束]

2)最多必须有1个额外的破坏,但它会显示3. [在程序结束时n = -3]

3)如果我以递归方式启用复制构造函数,则最终会创建副本,但结构总数为no = of destroy&#39;。 [在节目结束时n = 0]

这是lambda的行为(没有变数)吗?

或者它只是代码中的另一个错误?

lambda及其捕获变量的生命周期是什么?

2 个答案:

答案 0 :(得分:1)

假设你在代码中修复了未定义的行为,有些副本并不是很明显。

vp=[&f,b]
{
    //...
};

该声明中实际上有三份b

  1. 复制到lambda
  2. 复制到std::function构造函数
  3. 的参数中
  4. 复制到std::function
  5. 的内部存储空间

    前两个副本将在语句结束时销毁,因此您会看到两个破坏。它不是被摧毁两次的同一个物体。

    std::function必须进行类型擦除,因此它实际上可能非常昂贵。您可以使用合理的移动构造函数来缓解这种情况,但通常最好在可能的情况下使用原始的lambda类型。

答案 1 :(得分:0)

您的lambda对象通过引用捕获本地对象f,该对象在“块结束”打印之后超出范围(因此被销毁)。因此,在第二次调用vp()时,您有一个悬空引用,这是未定义的行为。