- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
的变体 std::unique_ptr in a loop - memory leaks
在这个修改过的问题中,RunSimulation()
是成员方法。
我想要一个 unique_ptr
sim
中的对象 ( main()
)在 main()
内到期另一个对象 ( r
) 发送到外部 main()
在 RunSimulation()
中释放.如果您能提供工作代码,那就太好了。
class Result { public: int n; };
class Simulation
{
public:
void RunSimulation(std::unique_ptr<Result> result) {result->n = 0;}
};
void main()
{
boost::thread_group threads;
std::unique_ptr<Result> r;
std::unique_ptr<Simulation> sim = std::make_unique<Simulation>();
for (int i = 0; i < 10; i++)
{
r = std::unique_ptr<Result>(new Result);
//Erroneous lines:
//threads.create_thread(boost::bind(&Simulation::RunSimulation, boost::ref(sim), std::move(r)));
//threads.create_thread([&] {sim->RunSimulation(std::move(r)); });
}
threads.join_all();
}
最佳答案
您试图传递 boost::bind
创建的仿函数至 create_thread
由于我在 answer 中解释的原因而失败对于您之前的问题。
使用 lambda 的尝试应该可以编译,但它有一个微妙的错误,会导致未定义的行为。我之前的回答可能误导了您,但这就是发布 MCVE 的原因是如此重要。您在上一个问题中发布的小片段并未显示您打算如何使用代码。
lambda 的问题是它只存储对 unique_ptr
的引用.在调用 RunSimulation
之前,您不会转让所有权执行,换句话说,所有权的转移只发生在线程执行开始之后。但到那时for
在 main
内循环可能已经进入下一次迭代,导致 Result
由 unique_ptr
持有在上一次迭代中被删除。取消引用 unique_ptr
在 RunSimulation
内然后导致未定义的行为。
解决这个问题的方法是转移 unique_ptr
的所有权立即转到 lambda,然后让 lambda 在对 RunSimulation
的调用中再次转移所有权.下面的 lambda 表达式做你想做的事
[&sim, r=std::move(r)] () mutable {
sim->RunSimulation(std::move(r));
}
为了解释发生了什么,lambda 正在捕获 sim
通过引用 ( &sim
) 并且它使用 C++14 的 lambda 初始化捕获来转移 r
的所有权在 main
内到 r
那是 lambda 的成员 ( r=std::move(r)
) lambda 本身需要是 r
因为你需要非 mutable
访问 const
数据成员所以你可以r
打电话的时候move
.
不幸的是,您的问题还没有结束。打电话RunSimulation
上面的 lambda 仍然无法编译,因为根据 documentation ,它要求可调用对象是可复制的。您的 lambda 不可复制,因为它有一个 create_thread
数据成员。
解决方法是创建一个 unique_ptr
然后 boost::thread
它到 add_thread
.
auto t = new boost::thread([&sim, r=std::move(r)] () mutable {
sim->RunSimulation(std::move(r));
});
threads.add_thread(t);
请注意,我找不到任何关于异常安全保证 thread_group
的文档使。所以有可能在 add_thread
时发生异常尝试将新线程添加到 add_thread
, 你的 thread_group
对象可能会泄漏。
最后,我认为您需要重新考虑您的设计。据推测,thread
对象应该保存模拟结果。有什么意义 Result
将其存储在 RunSimulation
中如果您无法访问 Result
在 Result
内模拟结束后?
正如我在之前回答的评论中所建议的那样,您可能应该创建一个 main
的容器在Result
并将对这些容器元素的引用传递给 main
.
关于c++ - 在循环中线程化 unique_ptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35641344/
我是一名优秀的程序员,十分优秀!