Почему поток C ++ вызывает деструктор несколько раз? - PullRequest
0 голосов
/ 24 октября 2019

Мне любопытно, почему простая программа на С ++, такая как та, что прикреплена ниже, несколько раз вызывает деструктор объекта work1 во время его обработки в std :: thread. Почему он вызывает деструктор несколько раз.

    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...

1 Ответ

1 голос
/ 24 октября 2019

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...