1

假设我有一个仿函数 F

struct F
{
    // <some member variables go here>
    void operator()() { while(true) /*do stuff affecting the state*/; }
};

如果我创建一个 Fs 向量

std::vector<F> functorVec(10);

然后用这些函子启动一堆线程

for (int i = 0; i < functorVec.size(); ++i)
{
    boost::thread(functorVec[i]); 
}

现在我对我的向量做了一些事情,比如

functorVec.push_back(F());

如果向量扩展并将其内容复制到新位置,这是否会导致线程中出现未定义的行为?还是他们会简单地崩溃?

似乎他们的状态发生了变化,可能是在他们正在对其进行的某些操作的中间。实际上,做这项工作的对象是被复制然后删除的,对吧?由于移动与线程的执行是异步的,所以这似乎是个坏消息。

我问是因为我希望能够保留一组对象,每个对象都运行自己的线程。这些对象表示附加到系统的模块。我希望能够即时添加和分离模块。如果将对象存储在集合中不是一个好主意,那么还有什么替代方法?我是否必须在堆上分配它们并将指针存储在我的集合中?

如果这根本不是问题,您能解释一下原因吗?

4

3 回答 3

3

boost::thread 的构造函数按值接受函子:

template <class F> explicit thread(F f);

这意味着它会复制您提供的仿函数,因此 id 不会引用您在仿函数向量中拥有的对象。因此,应该没有影响。

于 2013-08-02T06:57:33.677 回答
3

参考中

启动线程

通过将可调用类型的对象传递给构造函数来启动一个新线程,该对象可以在没有参数的情况下调用。然后将该对象复制到内部存储中,并在新创建的执行线程上调用。如果对象不能(或不能)被复制,则 boost::ref 可用于传入对函数对象的引用。在这种情况下,Boost.Thread 的用户必须确保被引用的对象比新创建的执行线程的寿命更长。

由于复制了线程参数,因此在所有线程启动后移动向量不会有问题。

于 2013-08-02T06:58:01.303 回答
3

根据boost::thread 文档,您根本不需要存储仿函数。可调用对象将在构造时被复制,并且您提供的原始对象将永远不会被再次引用。

于 2013-08-02T07:06:18.720 回答