在Qt中,我正在尝试建立自己的QWidget,因此一切都应该由于内存管理和其他事情而运行良好。但我似乎无法通过指针,堆和堆栈来完成任务。我的小部件MyWidget有一个带有一些对象的QList。我无法弄清楚如何正确设置一切。
您可以在下面看到我的代码,我对此有一些疑问:
在堆上创建instace变量列表,在堆栈上创建它会更好吗?
在我的列表中我有指针,是否最好只在堆栈上创建对象并将其附加到列表中? (所以我根本没有列表中的指针)
当我将对象追加到列表中时,他们会自动将列表作为父对象吗?那么当我删除列表时,列表中的所有对象都将被删除?
我正在尝试使用的每个循环都不起作用,我得到“这个操作需要一个指针/数组类型而不是'int'”
在我的代码中,我想创建其他小部件,将列表中的对象作为参数。这样做是否正确? MyOtherWidget的实例方法如下所示:MyOtherWidget(MyObject * myObject,QWidget * parent)
感谢您的帮助!我是Qt和C ++的新手,所以如果能引导我朝着正确的方向前进,那就太棒了。如何以正确的方式设置它以使其变得简单,不会因内存泄漏而使用尽可能少的内存。你会如何设置相同的东西?
这是我的代码:
MyWidget.h:
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(QWidget *parent = 0);
~MyWidget();
private:
QList<MyObject*> *list;
};
MyWidget.cpp:
MyWidget::MyWidget(QWidget *parent)
{
ui.setupUi(this);
list = new QList<MyObject*>();
for (int i = 0; i<10; i++)
{
MyObject *myObject = new MyObject("Hello",this);
list->append(myObject);
}
foreach(MyObject *myObject, list)
{
//Lets say I want to create other widgets here and that they takes a MyObject as a parameter
MyOtherWidget *myOtherWidget = new MyOtherWidget(myObject,this);
}
}
MyWidget::~MyWidget(){
delete list;
}
答案 0 :(得分:1)
Ad.1。列表的生命周期应该与MyWidget实例的生命周期相同,因此您可以安全地在堆栈上创建列表。
Ad.2。你可以这样做,但是MyObject类需要一个默认的构造函数,一个复制构造函数和一个赋值运算符(详见http://doc.trolltech.com/4.6/containers.html#container-classes)。
Ad.3。对象的所有权不会在追加时转移。就像STL容器一样,Qt容器不会在存储的指针上调用delete。要删除存储在QList(或其他Qt容器)中的所有指针,可以使用qDeleteAll(list)。请注意,您可能不希望在发布的代码中执行此操作:将MyWidget指针传递给MyObject构造函数,我认为它随后用作QObject父级。因此,当删除MyWidget时,将删除所有QObject。
Ad.4。 foreach宏的第二个参数应该是一个容器,而不是指向容器的指针。因此,如果列表变量是指向QList的指针,则应调用foreach(MyObject * obj,* list)。
Ad.5。只要MyOtherWidget不删除传递的MyObject(因为MyWidget已经是MyObject的父节点,并且你最终会删除两次相同的对象),你应该没问题。
这是一个严格的简化,但您应该尝试编写代码,以便您根本不需要调用delete。在堆栈上创建东西或依赖Qt父子机制(即父母删除他们的孩子)。稍后您可能想要了解智能指针(QSharedPointer,QScopedPointer等)。
编辑:
是否设置了MyObject的父级取决于您在MyObject构造函数中执行的操作。如果将父参数传递给QObject构造函数,即您的Myobject构造函数如下所示:
MyObject(const QString &text, QObject *parent = 0) : QObject(parent)
{
// more code...
}
将设置父级,因为它将在QObject构造函数中完成,该构造函数将由于“:QObject(父级)”代码而被调用。如果你没有这个片段怎么办?由于MyObject继承了QObject,并且您没有指定应该调用哪个构造函数,因此将调用默认的QObject构造函数,即QObject(QObject * parent = 0),因此MyObject的父级将为NULL,并且不会删除。
我会尽量避免通过setParent方法显式设置父级 - 对于基本用例,在构造函数中设置父级应该就足够了。
尝试使用正确的术语(不是“实例方法”,但“构造函数”),阅读Qt文档,使用常识并尽量不要认为任何事情都会自动完成。父进程不是“自动”设置的,因为你调用了一个参数“parent” - 它被设置,因为有一段代码在QObject构造函数中执行它,你有责任在类中调用传递适当的父代到QObject构造函数继承QObject。
答案 1 :(得分:0)
是的,问题是您要删除列表的对象而不是其元素!
我建议你看看:
QList<Employee *> list;
list.append(new Employee("Blackpool", "Stephen"));
list.append(new Employee("Twist", "Oliver"));
qDeleteAll(list.begin(), list.end());
list.clear();
我还会问你是否真的需要一个指向你名单的指针?你可以简单地说:
QList<MyObject*> list;
因此,您可能会减少一次内存泄漏!
希望这有点帮助!
编辑:
3.您的MyObject对象具有“this”作为父项。处理指针时,列表不会占用对象所有权
4.对于循环,也许你应该考虑迭代器,看看qthelp://com.trolltech.qt.460/qdoc/qlist.html。
答案 2 :(得分:0)
您不需要将子窗口小部件存储在列表中,只要您将它们设置为当前窗口小部件的父窗口即可。 (通常用新的方法在堆栈上创建小部件。)
Qt有一个自动清理功能,这意味着,如果一个小部件被删除,所有子窗口小部件(其父窗口被移除的窗口小部件的窗口小部件)都会被删除。
因此,您必须确保(特别是对于临时弹出窗口小部件)擦除/删除窗口小部件“弹出窗口”或者您调用弹出窗口小部件。
就是这样,就是这样。