2

在 Qt 中,我正在尝试设置自己的 QWidget,因此由于内存管理和其他事情,一切都应该正常工作。但我似乎无法用指针、堆和堆栈来解决问题。我有我的小部件 MyWidget,它有一个带有一些对象的 QList。我无法弄清楚如何正确设置所有内容。

您可以在下面看到我的代码,对此我有一些疑问:

  1. instace 变量列表是在堆上创建的,在栈上创建会更好吗?

  2. 在我的列表中,我有指针,在堆栈上创建对象并将其附加到列表中会更好吗?(所以我在列表中根本没有指针)

  3. 当我将对象附加到列表时,它们会自动将列表作为其父级吗?那么当我删除列表时,列表中的所有对象都会被删除吗?

  4. 我尝试使用的 for each 循环不起作用,我得到“此操作需要指针/数组类型而不是 'int'”

  5. 在我的代码中,我想创建其他小部件,将列表中的对象作为参数。这是像我一样做的正确方法吗?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;
};

我的小部件.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;
}
4

3 回答 3

1

广告1。列表的生命周期应该与 MyWidget 实例的生命周期相同,因此您可以安全地在堆栈上创建列表。

广告 2。您可以这样做,但 MyObject 类需要有一个默认构造函数、一个复制构造函数和一个赋值运算符(有关详细信息,请参阅http://doc.trolltech.com/4.6/containers.html#container-classes)。

广告 3。对象的所有权不会在追加时转移。就像 STL 容器一样,Qt 容器不会对存储的指针调用 delete。要删除存储在 QList(或其他 Qt 容器)中的所有指针,您可以使用 qDeleteAll(list)。请注意,您可能不想在您发布的代码中这样做:您将 MyWidget 指针传递给 MyObject 构造函数,我假设它随后用作 QObject 父级。所以当 MyWidget 被删除时,所有的 QObjects 都会被删除。

广告 4。foreach 宏的第二个参数应该是一个容器,而不是指向容器的指针。因此,如果您的列表变量是指向 QList 的指针,您应该调用 foreach(MyObject *obj, *list)。

广告 5。只要 MyOtherWidget 不删除传递的 MyObject 就可以了(因为 MyWidget 已经是 MyObject 的父级,并且您最终会删除同一个对象两次)。

这是一个粗略的简化,但是您应该尝试以根本不需要调用 delete 的方式编写代码。在堆栈上创建东西或依赖 Qt 父子机制(即父母删除他们的孩子)。稍后您可能想了解智能指针(QSharedPointer、QScopedPointer 等)。

编辑:

是否设置了 MyObject 的父级取决于您在 MyObject 构造函数中所做的事情。如果您将父参数传递给 QObject 构造函数,即您的 Myobject 构造函数如下所示:

MyObject(const QString &text, QObject *parent = 0) : QObject(parent)
{
// more code...
}

parent 将被设置,因为它将在 QObject 构造函数中完成,由于“:QObject(parent)”代码将调用该构造函数。如果你没有这个片段怎么办?由于 MyObject 继承了 QObject,并且您没有指定应该调用哪个构造函数,默认的 QObject 构造函数,即会调用 QObject(QObject *parent = 0),因此您的 MyObject 的父级将为 NULL 而不会删除。

我会尽量避免通过 setParent 方法显式设置父级 - 对于基本用例,在构造函数中设置父级就足够了。

尝试使用正确的术语(不是“实例方法”,而是“构造函数”),阅读 Qt 文档,使用常识,尽量不要认为任何事情都会自动完成。父级不会因为您调用一个参数“父级”而“自动”设置 - 它已设置,因为在 QObject 构造函数中有一段代码可以执行此操作,并且您有责任在类中调用将正确的父级传递给 QObject 构造函数继承QObject。

于 2010-03-29T13:55:45.217 回答
0

您不需要将子小部件存储在列表中,只要将它们设为当前小部件的父级即可。(通常您使用 new 在堆栈上创建小部件)。

Qt 有一个自动清理功能,这意味着,如果一个小部件被删除,所有子小部件(其父小部件是被删除的小部件)都会被删除。

因此,您唯一需要确保(尤其是临时弹出窗口小部件)擦除/删除窗口小部件“弹出窗口”,或者您调用弹出窗口小部件。

就是这样,仅此而已。

于 2010-03-29T20:28:09.617 回答
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

于 2010-03-29T13:34:23.400 回答