【问题标题】:Passing a shared_ptr or unique_ptr to _beginthreadex将 shared_ptr 或 unique_ptr 传递给 _beginthreadex
【发布时间】:2014-11-12 02:43:37
【问题描述】:

我想知道这是可能的。创建 TestClass 类型的 shared_ptr 或 unique_ptr。

然后调用 _beginthreadex 并将类的静态方法作为要执行的函数传递给它,并将之前创建的 shared_ptr 或 unique_ptr 作为数据传递给它。像这样:

shared_ptr<TestClass> p = make_shared<TestClass>(count, "test");
HANDLE hth1 = (HANDLE)_beginthreadex(NULL, 0, p->ThreadStart,p, 0, NULL);

我通常在没有智能指针的情况下使用这种方法,我通常创建一个 TestClass 的普通指针并将 TestClass 的静态方法和指针本身作为数据传递,然后在静态方法中将其转换为 (TestClass *) 并运行类的成员方法等,完成工作,当线程完成时,我删除指针。像这样的:

    TestClass * p = new TestClass(count, "test");
    HANDLE hth1 = (HANDLE)_beginthreadex(NULL, 0, p->ThreadStart,p, 0, NULL);

我想要实现的是让智能指针在线程结束时自动删除对象,因为智能指针会超出范围。

当我按照我在上面描述的方式进行操作时,编译器会显示此错误:

“不存在从“std::shared_ptr”到“void *”的合适转换函数”

【问题讨论】:

  • 您考虑过使用standard thread 库吗?那么就完全有可能
  • 如果我不能像第一次尝试那样做,那是我的下一步行动
  • 这似乎是对shared_ptr 的一种特别愚蠢的用法。哦,让我们使用这个共享指针。但它是共享的,我们不希望它被共享。没关系,我们会设法让它表现得像不共享一样。但是……为什么要这样做呢?如果您已经拥有shared_ptr 或出于某种原因需要它(也许线程需要延长对象的生命周期),这将非常有意义。但是创建一个只是为了撤销其唯一目的……太疯狂了!
  • 大卫,我不认为你明白我的要求,但没关系,反正 txs

标签: c++ c++11 shared-ptr smart-pointers unique-ptr


【解决方案1】:

_beginthreadex看起来像c函数,要实现你想要的,你需要调用复制构造函数(或unique_ptr的情况下是move)来传输所有权,这在 c 中是不可能的。

您可以考虑使用 std::thread 类,它与 std 套件的其余部分配合得很好。

假设你想运行:

void ThreadStart(std::shared_ptr<TestClass> p);

你可以通过

void ThreadStart(std::shared_ptr<TestClass> p)
{
    cout << p->count << " " << p->name << endl;
}

int main()
{
    shared_ptr<TestClass> p = make_shared<TestClass>(33, "test");
    std::thread thr(ThreadStart, p);
    thr.join();
}

如果是std::unique_ptr你需要std::move它到线程函数,所以它实际上会在线程结束时被删除:

void ThreadStart(std::unique_ptr<TestClass> p);
...
unique_ptr<TestClass> p = make_unique<TestClass>(33, "test");
std::thread thr(ThreadStart, std::move(p));

【讨论】:

  • txs,但在此示例中,主线程比衍生线程长。在我的情况下,我想在主线程上创建对象,在另一个线程中使用它们并在生成的线程结束时摆脱它们。我想利用 smart_ptr 在超出范围时释放对象的事实,这可能在生成的线程中以多种方式发生。使用原始指针,如果您不执行删除操作,则必须小心不要泄漏内存。
  • std::thread 超出范围时,默认终止派生线程,但您可以调用thr.detatch() 而不是thr.join(),因此主线程不会等待派生线程的终止。
【解决方案2】:

使用shared_ptr::getunique_ptr::get 来访问指向托管对象的指针。

shared_ptr<TestClass> p = make_shared<TestClass>(count, "test");
HANDLE hth1 = (HANDLE)_beginthreadex(NULL, 0, p->ThreadStart, p.get(), 0, NULL);

【讨论】:

  • 将原始指针传递给另一个线程是否安全?您没有将所有权传递给它。如果 shared_ptr 在调用者中删除了拥有的对象呢?
  • @RafalMielniczuk 这将是一个问题。 OP 需要确保智能指针在线程完成之前保持活动状态。
  • @user3196371 可能是因为shared_ptr 超出范围,并删除了托管对象。您需要确保在线程完成执行之前不会发生这种情况。您看到的异常与使用 get 访问原始指针没有任何关系。
猜你喜欢
  • 1970-01-01
  • 2016-01-05
  • 2012-03-30
  • 1970-01-01
  • 2015-05-03
  • 2018-03-12
  • 1970-01-01
  • 2015-09-03
  • 2013-01-16
相关资源
最近更新 更多