Cap*_*man 42 c++ multithreading constructor infinite-loop
假设我有一个在无限循环中提供某种功能的对象。
将无限循环放在构造函数中是否可以接受?
例子:
class Server {
public:
Server() {
for(;;) {
//...
}
}
};
Run Code Online (Sandbox Code Playgroud)
或者如果构造函数永远不会完成,C++ 中是否存在固有的初始化问题?
(这个想法是运行你刚才说的服务器Server server;,可能在某个线程中......)
Dav*_*aim 76
根据标准,这并没有错,这只是一个糟糕的设计。
构造函数通常不会阻塞。它们的目的是获取原始内存块,并将其转换为有效的 C++ 对象。析构函数做相反的事情:它们获取有效的 C++ 对象并将它们转换回原始内存块。
如果你的构造函数永远阻塞(强调永远),它会做一些不同的事情,而不仅仅是将一块内存变成一个对象。如果这服务于对象的构造,则可以短时间阻塞(互斥锁就是一个很好的例子)。在您的情况下,看起来您的构造函数正在接受和服务客户。这并不是将内存变成对象。
我建议您将构造函数拆分为构建服务器对象的“真实”构造函数和start为客户端提供服务的另一个方法(通过启动事件循环)。
ps:在某些情况下,您必须与构造函数分开执行对象的功能/逻辑,例如,如果您的类继承自std::enable_shared_from_this.
Hol*_*Cat 18
这是允许的。但与任何其他无限循环一样,它必须具有可观察到的副作用,否则会出现未定义的行为。
调用网络函数算作“可观察到的副作用”,所以你很安全。该规则仅禁止循环,这些循环要么实际上什么都不做,要么只是在不与外部世界交互的情况下混洗数据。
Cor*_*ica 16
它是合法的,但避免它是一个好主意。
主要问题是您应该避免让用户感到惊讶。有一个从不返回的构造函数是不寻常的,因为它不合逻辑。你为什么要建造一些你永远无法使用的东西?因此,虽然该模式可能有效,但它不太可能是预期的行为。
第二个问题是它限制了您的 Server 类的使用方式。C++ 的构造和销毁过程是该语言的基础,因此劫持它们可能很棘手。例如,一个人可能想要一个Server是类的成员,但现在总体类的构造函数将阻塞......即使这不直观。这也使得将这些对象放入容器变得非常困难,因为这可能涉及分配许多对象。
我能想到的最接近你正在做的事情是std::thread. Thread 不会永远阻塞,但它确实有一个构造函数可以完成惊人的大量工作。但是,如果您查看std::thread,您就会意识到当涉及到多线程时,感到惊讶是常态,因此人们对此类选择的麻烦较少。(我个人不知道在构造时启动线程的原因,但是多线程中有很多极端情况,如果它解决了其中的一些问题,我不会感到惊讶)
| 归档时间: |
|
| 查看次数: |
4236 次 |
| 最近记录: |