-1

对于像这样微不足道的事情,在堆栈上创建 QProcess 有什么缺点吗

void Utils::changeFont()
{
    QString command("book");
    QStringList arguments({"opensans", "10"});
    QProcess fontProcess;
    fontProcess.start(command,arguments);
    fontProcess.waitForFinished();
}  

我创建了 10 个 Utils 对象;

Utils a , b , c .....,

都分别调用Utils::changeFont()

进程在堆栈上会更好吗

我问是因为我没有看到它在任何教程中被这样使用。

谢谢

4

3 回答 3

4

这里的问题与“在堆栈上”创建 QProcess 无关。实际上,堆栈是用词不当:您真正要问的是“我可以将 QProcess 创建为局部变量吗”。是的,你当然可以!

但是这样QProcess是没用的,因为你不应该使用这些waitFor方法 - 永远不会。它们是一个可怕的 API。不要使用它们:相反,编写异步代码 - 即对QProcess. 在您的情况下,您只需要在该过程完成后删除该对象。因此:

// Not a class!!
namespace Utils {
void changeFont()
{
    QString command("book");
    QStringList arguments({"opensans", "10"});
    auto *fontProcess = new QProcess(context);
    QObject::connect(fontProcess, 
                     qOverload<int, QProcess::ExitStatus>(&QProcess::finished),
                     fontProcess, &QProcess::deleteLater);
    fontProcess->start(command,arguments);
}
}

请注意,它Utils不应该是一个类——它是一种糟糕的 Java 主义。如果要在命名空间中对实用程序函数进行分组,请使用命名空间!这就是它们的用途:)changeFont所呈现的不应该是一种方法,因为它只是成为一种静态方法,此时您不需要任何状态。如果你需要状态,那么这个类需要比它更具体Utils——它可能是一个适应QProcess你特定用途的类,但它需要非常具体,否则你最终会得到深度耦合的意大利面条代码。

在 C++ 中,几乎没有理由拥有Utils一个类。这是代码审查中的典型危险信号。它需要是一个命名空间,如果你真的需要一个保持状态的类,它必须是一个特定于任务的类,它只做一件事并且做得很好,并且没有其他功能。

如果您需要在流程完成后继续您正在进行的任何工作,您应该创建一个状态机并在流程完成时对状态转换做出反应,并在那里执行后续操作。这样,您还可以明确在出现错误时该怎么做。当您编写伪同步代码时,这些问题就会被掩盖。如果你的代码有任何waitFor调用,它基本上已经坏了——你只是还不知道。Qt 对每个人都造成了严重的伤害,因为它提供了这些伪同步方法。他们的所有好处是冻结用户界面。如果你有点关心你的用户体验,那就太糟糕了。

于 2020-09-28T15:04:35.923 回答
3

new QProcess(parent)来自文档的示例还分配了一个 parent QObjectQProcess如果流程超出示例默认假设的范围,您将需要该(或其他所有权策略) 。

在您的情况下,您正在调用waitForFinished(),所以如果QProcess在函数结束时删除它就可以了。没有必要让它活得更久。

于 2020-09-28T14:46:32.640 回答
1

没关系,实际上 Qt 文档中的几乎所有示例都显示QProcess了堆栈上的创建。

唯一的缺点是对象本身的创建。如果您“经常”需要它,那么创建一次可能会更好。

于 2020-09-28T14:41:34.337 回答