C++ QT图像查看器示例,可能的内存泄漏?
QT文档网站上的包含以下代码段:C++ QT图像查看器示例,可能的内存泄漏?,c++,qt,C++,Qt,QT文档网站上的包含以下代码段: ImageViewer::ImageViewer() : imageLabel(new QLabel) , scrollArea(new QScrollArea) , scaleFactor(1) { imageLabel->setBackgroundRole(QPalette::Base); imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ign
ImageViewer::ImageViewer()
: imageLabel(new QLabel)
, scrollArea(new QScrollArea)
, scaleFactor(1)
{
imageLabel->setBackgroundRole(QPalette::Base);
imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
imageLabel->setScaledContents(true);
scrollArea->setBackgroundRole(QPalette::Dark);
scrollArea->setWidget(imageLabel);
scrollArea->setVisible(false);
setCentralWidget(scrollArea);
createActions();
resize(QGuiApplication::primaryScreen()->availableSize() * 3 / 5);
}
其中imageLabel
和scrollArea
分别是指向QLabel
和QScrollArea
的指针成员
我理解在scrollArea->setWidget(imageLabel)行中代码>滚动区域拥有imageLabel指针的所有权,并在需要时将其删除。同样适用于setCentralWidget(滚动区域)代码>其中窗口拥有滚动区域的所有权
但是,在构建过程中,如果imageLabel
创建成功,但是scrollArea
创建失败,那么imageLabel
是否会泄漏
如果是,解决这个问题的标准方法是什么?我认为有两种方法:
1。使用智能指针而不是原始指针(例如QPointer
)
更多细节可能会被发现(道德4是关于你的问题)现在就这样解决它:
ImageViewer::ImageViewer()
: scaleFactor(1)
{
//Manage pointers with unique_ptr until it's time to transfer ownership.
auto uniqueImageLabel = std::make_unique<QLabel>();
auto uniqueScrollArea = std::make_unique<QScrollArea>();
//Copy pointers to members for access as per normal.
imageLabel = uniqueImageLabel.get();
scrollArea = uniqueScrollArea.get();
imageLabel->setBackgroundRole(QPalette::Base);
imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
imageLabel->setScaledContents(true);
scrollArea->setBackgroundRole(QPalette::Dark);
//ScrollArea now takes ownership of image label.
scrollArea->setWidget(uniqueImageLabel.release());
scrollArea->setVisible(false);
//Window now takes ownership of scroll area.
setCentralWidget(uniqueScrollArea.release());
createActions();
resize(QGuiApplication::primaryScreen()->availableSize() * 3 / 5);
}
ImageViewer::ImageViewer()
:scaleFactor(1)
{
//使用unique_ptr管理指针,直到转移所有权。
auto uniqueImageLabel=std::make_unique();
auto uniqueScrollArea=std::make_unique();
//将指针复制到成员以按正常方式访问。
imageLabel=uniqueImageLabel.get();
scrollArea=uniqueScrollArea.get();
imageLabel->setBackgroundRole(QPalette::Base);
imageLabel->setSizePolicy(QSizePolicy::忽略,QSizePolicy::忽略);
图像标签->设置缩放内容(真);
scrollArea->setBackgroundRole(QPalette::Dark);
//ScrollArea现在拥有图像标签的所有权。
scrollArea->setWidget(uniqueImageLabel.release());
滚动区域->设置可见(假);
//窗口现在拥有滚动区域的所有权。
setCentralWidget(uniqueScrollArea.release());
createActions();
调整大小(QGuiApplication::primaryScreen()->availableSize()*3/5);
}
好吧,这可能是Qt的一个总体问题,因为它不是完全异常安全的
从实用的角度来看,除非您创建关键任务应用程序,否则这并不重要。如果滚动区域的构建(即动态分配)失败,那么这意味着发生了非常可怕的事情:所有的内存都耗尽了,甚至不将内存交换到磁盘都有助于解决这个问题。在这种情况下,内存泄漏是您最不关心的问题。您可能会崩溃或完全冻结您的计算机无论如何,重新启动将是必要的
当然,您可以尝试使用智能指针解决部分代码,但它仍然可能在Qt库本身中留下大量漏洞。如果你的内存完全用完,你的程序无论如何都会失灵
因此,除非您创建真正防弹的关键任务应用程序,否则您可能不需要关心这种情况。如果我是你,我会更关心系统性内存泄漏,在正常情况下你会忘记释放内存
除非创建任务关键型应用程序,否则不必担心内存不足。这是一个“vis maior”,当这种情况出现时,你几乎无法采取任何措施来保护你的应用程序。好消息是,我们大多数人在正常情况下从未经历过这种情况
ImageViewer::ImageViewer()
: imageLabel(nullptr)
, scrollArea(nullptr)
, scaleFactor(1)
{
try {
imageLabel = new QLabel();
scrollArea = new QScrollArea();
} catch (std::bad_alloc&) {
delete imageLabel;
delete scrollAreal;
}
// ...
}
ImageViewer::ImageViewer()
: scaleFactor(1)
{
//Manage pointers with unique_ptr until it's time to transfer ownership.
auto uniqueImageLabel = std::make_unique<QLabel>();
auto uniqueScrollArea = std::make_unique<QScrollArea>();
//Copy pointers to members for access as per normal.
imageLabel = uniqueImageLabel.get();
scrollArea = uniqueScrollArea.get();
imageLabel->setBackgroundRole(QPalette::Base);
imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
imageLabel->setScaledContents(true);
scrollArea->setBackgroundRole(QPalette::Dark);
//ScrollArea now takes ownership of image label.
scrollArea->setWidget(uniqueImageLabel.release());
scrollArea->setVisible(false);
//Window now takes ownership of scroll area.
setCentralWidget(uniqueScrollArea.release());
createActions();
resize(QGuiApplication::primaryScreen()->availableSize() * 3 / 5);
}