在 Qt 中的 VideoWidget 和 Secure Socket Client 示例中,提供的代码在父小部件中初始化子小部件,如下所示:
SslClient::SslClient(QWidget *parent)
: QWidget(parent), socket(0), padLock(0), executingDialog(false)
和
VideoPlayer::VideoPlayer(QWidget *parent)
: QWidget(parent)
, mediaPlayer(0, QMediaPlayer::VideoSurface)
, playButton(0)
, positionSlider(0)
, errorLabel(0)
但是,在代码的更下方,我看到以下内容:
playButton = new QPushButton;
或者在安全套接字客户端的情况下,这:
padLock = new QToolButton;
为什么要在代码中初始化时在构造函数中初始化?
最佳答案
Why initalise in the constructor when it will be initalised in the code?
这样实现是异常安全的。假设您有以下代码:
SslClient::SslClient(QWidget *parent)
: QWidget(parent), socket(0), padLock((QToolButton*)(0x0BEEF)), executingDialog(false) {
throw std::exception();
padLock = new QToolButton;
}
析构函数将删除 padLock
,但它具有垃圾值,并且您有未定义的行为。回想一下,删除 nullptr 是安全的(就像在 C 中调用 free(NULL)
一样!)。垃圾挂锁值显示当您不初始化它时会发生什么。抛出表明一些中间代码可能会抛出。具体来说,如果分配无法成功,任何介入的 new
都会抛出异常。 new
不会在失败时返回(如:它抛出 std::bad_alloc
而不是返回,因此返回值的概念根本不适用)。
如果一个人正在编写惯用的 C++,那么指针不应该是一个裸指针,而是一个 std::unique_ptr
或 QScopedPointer
,然后这个问题就消失了。您不必记得将指针初始化为零,也不必记得清理它。 RAII 给你很多胜利。当您真正按照 C++ 的使用方式使用它时,这就是您获得的 secret 武器。
C++ RAII 惯用语本身不存在于任何其他通用编程语言中。在允许它的语言中(例如 Java、C#、F#、Python、OCaml 和 Common Lisp),惯用的解决方法是定义一个高阶 with_resource
函数,参见 OCaml 的示例, Java 和 Python 和 Python again 。基本上,在 C++ 以外的语言中,尤其是在垃圾收集语言中,内存资源释放的处理方式不同于非内存资源释放。在 C++ 中,它们统一在 RAII 保护伞下。
关于c++ - qt - 在父窗口/小部件类中初始化子小部件的目的是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21964662/