【问题标题】:C++ - are these threads destroyed after the for loop is completedC ++ - 这些线程在for循环完成后是否被销毁
【发布时间】:2017-10-18 14:14:04
【问题描述】:
for (int i = 0; i < 10; i++) {
    thread *t = new thread(example_function);
    t->join();
}

我在我的一个编码项目中做类似的事情,我想知道是否因为线程在循环内被定义,所以它们在循环结束后被销毁(我知道指向线程的指针可能被删除但是线程本身呢?)。

【问题讨论】:

  • 一般在使用new的时候分配内存,需要使用delete删除,否则内存区域会一直分配到程序结束
  • @TemaniAfif 你的意思可能是delete
  • @Ron 是的! free 是用 malloc 的,只是一个错误...

标签: c++ multithreading concurrency


【解决方案1】:

不,在for 循环内创建的thread 对象不会被破坏,这意味着它们会造成内存泄漏。

为了确保线程被销毁,您需要通过以下几种方式之一对它们调用delete

  • 在作用域结束时调用delete,或
  • 将线程指针添加到指针容器中,并在单独的循环中调用delete,或者
  • 将线程指针添加到智能指针以确保在作用域结束时删除,或
  • 将线程指针添加到智能指针容器中,并让容器在超出范围时删除线程。

请注意,由于您在每次循环迭代中调用join,您的“并发”程序与单线程程序一样好。以下是如何同时运行您的线程,并确保在最后删除线程:

std::vector<std::unique_ptr<std::thread>>> threads;
for (int i = 0; i < 10; i++) {
    threads.push_back(std::make_unique<thread>(example_function));
}
for (int i = 0; i < 10; i++) {
    threads[i]->join();
}

一旦threads 向量超出范围,它会删除其中的std::unique_ptr&lt;thread&gt; 对象,进而在各个std::thread 对象上调用delete

【讨论】:

  • @user3572917 是的,因为您不会立即等待刚刚启动的线程。您将它们全部创建,然后开始等待每个。
  • make_unique里面不需要new(并不是说不需要整个动态分配)
  • @Slava 你是对的,他们将参数转发给实际的new。谢谢!啊,你说得对,在这个例子中不需要动态分配。
【解决方案2】:

我在我的一个编码项目中做类似的事情,我想知道线程是否在循环内定义,它们在循环结束后被销毁

使用运算符new 进行动态分配的全部目的是提供对对象生命周期的手动控制。所以不,除非您明确调用 delete 或者您使用智能指针在后台为您执行此操作,否则您的对象不会被破坏。请注意,在循环内有效地调用std::thread::join() 会使您的程序成为单线程的。更正确的用法是:

std::vector<std::thread> threads;
while( threads.size() < 10 )
    threads.emplace_back(example_function);

for( auto &thread : threads )
    thread.join(); // join in a separate loop, let all threads to start

threads.clear(); // or let it go out of scope

【讨论】:

  • 我也是这么想的,只是将代码放入{ } 以创建并发执行的范围。
【解决方案3】:

这里

thread *t = new thread(example_function);

您已经丢失了以前分配的 thread 实例并且发生了内存泄漏。

join() 不会释放分配的内存,但会获取异步结束的函数。

【讨论】:

    【解决方案4】:

    没有。调用者负责确保使用new 分配的对象是deleted。

    代码当然毫无意义,因为没有发生有意义的并发,但为了避免内存泄漏应该是:

    for (int i = 0; i < 10; i++) {
        thread *t = new thread(example_function);
        t->join();
        delete t;
    }
    

    在 C++11 以后的任何版本中,建议您在这些情况下使用 std::unique_ptr

    最推荐的形式是:

    auto t{std::make_unique<std::thread>(example_function)};
    

    这几乎等同于:

    std::unique_ptr<std::thread> t(new std::thread(example_function));
    

    std::unique_ptr 是一个具有运算符重载的对象,其行为很像指针,不同之处在于在其生命周期结束时删除它指向的事物(如果有的话)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-23
      • 1970-01-01
      • 2011-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多