gpt4 book ai didi

c++ - 如何让std::thread在执行完其成员函数后自动删除对象

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:03:08 25 4
gpt4 key购买 nike

我想实现一个 cmmand 类,它在另一个线程中做一些工作,我不想让用户手动删除该对象。我的 command 像这样上课:

class Cmd {
public:
void excute() {
std::cout << "thread begins" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2)); // do some work
std::cout << "thread ends" << std::endl;
}

void run() {
// I want std::unique_ptr to delete 'this' after work is done,but does't work
std::thread td(&Cmd::excute, std::unique_ptr<Cmd>(this));
td.detach();
}

// test if this object is still alive
void ok() { std::cout << "OK" << std::endl; }
};

我是这样使用的:

int main() {
Cmd *p = new Cmd();
p->run();

// waiting for cmd thread ends
std::this_thread::sleep_for(std::chrono::seconds(3));

p->ok(); // I thought p was deleted but not

return 0;
}

如评论中所述,在 cmd 线程完成后该对象仍然存在,我想知道如何实现这种功能。

编辑

cmd 的用户不知道cmd 什么时候结束,所以流动的用例会导致 UB。

std::unique_ptr<Cmd> up(new Cmd);  // or just Cmd c;
up->run();
// cmd will be deleted after out of scope but cmd::excute may still need it

关闭

我测试的时候弄错了,实际上对象是在线程结束后被删除的。下面的测试加一个成员变量int i会更清楚。

#include <functional>
#include <iostream>
#include <stack>
#include <thread>

using namespace std;

class Cmd {
public:
~Cmd() { std::cout << "destructor" << std::endl; }

void excute() {
std::cout << i << " thread begins" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2)); // do some work
std::cout << i << " thread ends" << std::endl;
}

void run() {
// I want std::unique_ptr to delete 'this' after work is done,but it seems
// not working
std::thread td(&Cmd::excute, std::unique_ptr<Cmd>(this));
td.detach();
}

// test if this object is still alive
void ok() { std::cout << i << " OK" << std::endl; }

int i;
};

int main() {
Cmd *p = new Cmd();
p->i = 10;
p->run();

// waiting for cmd thread ends
std::this_thread::sleep_for(std::chrono::seconds(3));

p->ok(); // I thought p was deleted but not

return 0;
}

flowwing 输出证明对象已被删除。

10 thread begins
10 thread ends
destructor
-572662307 OK

但正如一些好心人所建议的那样,这不是一个好的设计,请尽可能避免。

最佳答案

您可以使用 std::future 而不是线程向国家发出信号。然后,您可以等待任务完成,也可以完全忽略 future 。

#include <future>
#include <chrono>
#include <mutex>
#include <iostream>

class Cmd {
public:
std::future<void> run() {
std::lock_guard<std::mutex> lock(startMutex);
if (started) {
throw std::logic_error("already started");
}
started = true;

// Take copies here, so that it doesn't matter if Cmd is destroyed
int i_ = i;
return std::async(std::launch::async, [i_]() {
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << i_ << std::endl;
});
}

int i = 0;

private:
std::mutex startMutex;
bool started = false;
};

int main() {
auto p = std::make_unique<Cmd>();
p->i = 10;
auto f = p->run();
p.reset();

// Do some other work

// Wait for the task to finish (or use f.get() if there is no need to
// do some other work while waiting)
if (f.valid()) {
std::future_status operation;
do {
// Do some other work

operation = f.wait_for(std::chrono::milliseconds(1));
} while (operation != std::future_status::ready);
}
}

关于c++ - 如何让std::thread在执行完其成员函数后自动删除对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55821782/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com