在堆栈上创建 QLayout 是否安全
Is it safe to create a QLayout on the stack?
我知道Qt文档,QLayout
对象拥有其小部件的所有权。但就QLayout
对象而言,在堆栈上创建它,然后使用 setLayout
函数将其传递给小部件是否安全?还是必须在堆上创建?
#include <iostream>
#include <QtGui/QApplication>
#include <QPushButton>
#include <QVBoxLayout>
class LoudPushButton : public QPushButton
{
public:
virtual ~LoudPushButton(){std::cout << "~LoudPushButton()" << std::endl;}
};
class LoudQVBoxLayout : public QVBoxLayout
{
public:
virtual ~LoudQVBoxLayout(){std::cout << "~LoudQVBoxLayout()" << std::endl;}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget window;
// On the heap
LoudQVBoxLayout* mainlayout = new LoudQVBoxLayout;
mainlayout->addWidget(new LoudPushButton);
mainlayout->addWidget(new LoudPushButton);
window.setLayout(mainlayout);
/*
// On the stack
LoudQVBoxLayout mainlayout;
mainlayout.addWidget(new LoudPushButton);
mainlayout.addWidget(new LoudPushButton);
window.setLayout(&mainlayout);
*/
window.show();
return a.exec();
}
两种选择//在堆栈上和//在堆上在退出处产生相同的结果:
~LoudQVBoxLayout()
~LoudPushButton()
~LoudPushButton()
但我能确定这不是未定义的行为吗?window
是否在其布局上调用delete
?
编辑:
鉴于Cat Plus Plus的答案,我猜:
LoudPushButton button;
mainlayout->addWidget(&button);
mainlayout->addWidget(new LoudPushButton);
即使保证同时删除button
和*mainlayout
,也会产生未定义的行为。这是真的吗?
每个QObject
都会删除其子项。只有没有父对象的对象才能具有自动存储。QWidget::setLayout
重新设置布局。所以,不,你不能用QLayout
做到这一点.
在Qt中,对象树的设计使得QWidgets可以在堆栈上构建。只要父母先于孩子被创造,他们就会正确地破坏。你的两个例子都不是未定义的行为。
Qt文档甚至给出了一个例子,并解释了为什么在堆栈上构造带有父级的小部件是合法的:
int main()
{
QWidget window;
QPushButton quit("Quit", &window);
...
}
此代码是正确的:quit 的析构函数不会调用两次,因为C++语言标准 (ISO/IEC 14882:2003( 指定本地对象的析构函数按其构造函数的相反顺序调用。因此,首先调用子项的析构函数 quit,并在调用 window 析构函数之前将自身从其父窗口中删除。
布局也应该表现正常,因为它们被设计为随时被破坏。QWidget::setLayout
文档提到:
如果此小部件上已经安装了布局管理器,QWidget将不允许您安装另一个布局管理器。必须先删除现有的布局管理器(由 layout(( 返回(,然后才能使用新布局调用 setLayout((。
Qt布局系统跟踪在QWidgets上设置的QLayout对象的生命周期,并将适当地处理销毁,如本文档所暗示的那样。QLayout 的析构函数包含从设置它的 QWidget 中注销它的代码。
- 通过网络、跨平台传递std::变体是否安全
- 在类型和包装器之间reinterpret_cast是否安全<Type>?
- 跨 DLL 边界访问虚拟方法是否安全/可能?
- 静态 constexpr 类成员变量对多线程读取是否安全?
- 在函数结束后使用指向变量的指针是否安全?
- 逐字节删除 void* 是否安全?
- 在 RAII 构造中修改 RVO 值是否安全?
- 线程调用的函数对对象删除是否安全?
- 将对象的字节复制到数组并再次复制回来是否安全
- 使用枚举为数组编制索引是否安全?
- 返回从字符串文本创建的静态string_view是否安全?
- 在cstlib中将#include_next替换为#include是否安全
- 由并发无序映射查找线程调用的函数是否安全?
- 使用 c++ 原子时编写"y=++x"是否安全?
- 从另一个线程发出信号是否安全?
- 从其存储的回调中删除 std::函数是否安全
- 使用 std::vector::swap 方法在C++中交换两个不同的向量是否安全?
- 当我在C++中调用 struce 的只读静态成员时,线程是否安全
- 同时调用 ASIO 对象的 API 是否安全?
- 使用自己的迭代器分配容器是否安全?