为什么 C++ 线程多次调用析构函数?

阿努巴夫·罗哈吉

我很好奇为什么像下面附加的一个简单的 C++ 程序在 std::thread 中处理 work1 对象时多次调用它的析构函数。为什么它多次调用析构函数。

    class work1 {
    public:
    work1(int x_) : x(x_) {
        ++count;
        std::cout<<"\n[WORKER1] Ctor : "<<count<<std::endl;
    }

    ~work1() {
        std::cout<<"\n[WORKER1] Dtor : "<<count<<std::endl;
    }

    void operator() () {
        for(int i =0; i < x; ++i) {
            std::cout<<"[WORKER1] Printing this :: "<<i<<std::endl;
        }
    }

    private:
        int x;
        static int count;
    };

int main()
{
    int local_main=5;
    std::thread t((work1(local_main)));
    t.join();    
    std::cout<<"\n[MAIN] From main thread..."<<std::endl;
    return 0;
}

上面的代码产生以下输出:

[WORKER1] Ctor : 1
[WORKER1] Dtor : 1
[WORKER1] Dtor : 1
[WORKER1] Printing this :: 0
[WORKER1] Printing this :: 1
[WORKER1] Printing this :: 2
[WORKER1] Printing this :: 3
[WORKER1] Printing this :: 4
[WORKER1] Dtor : 1
[MAIN] From main thread...
马克西姆·叶戈鲁什金

std::thread通过调用复制构造函数来复制参数。实现复制构造函数以观察副本:

class work1 {
public:
    work1(int x_) : x(x_) {
        ++count;
        std::cout << __PRETTY_FUNCTION__ << ' ' << count << '\n';
    }

    work1(work1 const& other)
        : x(other.x)
    {
        ++count;
        std::cout << __PRETTY_FUNCTION__ << ' ' << count << '\n';
    }

    work1& operator=(work1 const& other)
    {
        x = other.x;
        std::cout << __PRETTY_FUNCTION__ << ' ' << count << '\n';
        return *this;
    }

    ~work1() {
        --count;
        std::cout << __PRETTY_FUNCTION__ << ' ' << count << '\n';
    }

    void operator() () {
        for(int i =0; i < x; ++i) {
            std::cout<<"[WORKER1] Printing this :: "<<i<<std::endl;
        }
    }

private:
    int x;
    static int count;
};

int work1::count;

int main() {
    int local_main=5;
    std::thread t((work1(local_main)));
    t.join();
}

输出:

work1::work1(int) 1
work1::work1(const work1&) 2
work1::work1(const work1&) 3
work1::~work1() 2
work1::~work1() 1
[WORKER1] Printing this :: 0
[WORKER1] Printing this :: 1
[WORKER1] Printing this :: 2
[WORKER1] Printing this :: 3
[WORKER1] Printing this :: 4
work1::~work1() 0

如果您想避免复制传递对功能对象的引用,则该线程使用std::ref

int main() {
    work1 w{5};
    std::thread t(std::ref(w));
    t.join();
}

输出:

work1::work1(int) 1
[WORKER1] Printing this :: 0
[WORKER1] Printing this :: 1
[WORKER1] Printing this :: 2
[WORKER1] Printing this :: 3
[WORKER1] Printing this :: 4
work1::~work1() 0

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么在构造时调用C ++类的析构函数?

为什么在调用luaL_error时未调用C ++对象析构函数?

什么时候调用C ++析构函数?

C ++为什么调用此析构函数,它从何而来

C ++为什么在堆栈中构造完对象后立即调用析构函数?

为什么 C++ 中类字段的默认初始化需要析构函数调用?

C ++:简单的任务,析构函数被多次调用

C ++我听不懂为什么要调用“父类静态函数”,而只调用父析构函数

为什么要调用析构函数

为什么不调用析构函数?

为什么C ++偏向于析构函数的异常?

C ++:为什么析构函数的设计不像删除指针?

什么时候在C ++中调用要调用的对象的析构函数?

为什么析构函数比构造函数调用得更多?

为什么在Friend函数中调用析构函数

什么时候在堆中的对象上调用C ++析构函数?

C ++在析构函数中杀死线程

为什么同一个类对象的构造函数和析构函数被隐式调用多次

为什么不调用继承类的析构函数?

为什么在父类之前调用子类的析构函数?

为什么代码两次调用析构函数?

为什么我的类析构函数立即被调用?

为什么在执行复制之前调用析构函数?

为什么要调用派生类的析构函数?

为什么调用从对象移出的析构函数?

为什么析构函数被调用两次?

为什么析构函数调用两次表单?

为什么在复制分配期间调用析构函数?

为什么在“返回 0”后调用析构函数?