我是Qt的新手,并试图学习成语.
该foreach文件说:
Qt在进入foreach循环时自动获取容器的副本.如果在迭代时修改容器,则不会影响循环.
但它没有说明如何在迭代时删除元素foreach.我最好的猜测是这样的:
int idx = 0;
foreach (const Foo &foo, fooList) {
if (bad(foo)) {
fooList.removeAt(idx);
}
++idx;
}
Run Code Online (Sandbox Code Playgroud)
看起来很丑陋,不得不idx在循环外部(并且必须保持一个单独的循环计数器).
此外,我知道这是的,深层复制发生了.foreach是一个QList便宜的副本,但是一旦我删除一个元素会发生什么 - 是否仍然便宜或是否有昂贵的复制修改?
编辑:这似乎不是惯用的Qt.
for (int idx = 0; idx < fooList.size(); ) {
const Foo &foo = fooList[idx];
if (bad(foo)) {
fooList.removeAt(idx);
}
else ++idx;
}
Run Code Online (Sandbox Code Playgroud) 初始化QList的正确方法是什么?我想让这段代码更短:
QSplitter splitter;
QList<int> list;
list.append(1);
list.append(1);
splitter.setSizes(list);
Run Code Online (Sandbox Code Playgroud)
但是当我从std :: list使用初始化时,它似乎不起作用:
splitter.setSizes(QList<int>::fromStdList(std::list<int>(1, 1)));
Run Code Online (Sandbox Code Playgroud)
在后一种情况下,分离器似乎以1:0的比例分开.
如果我在C++中有一个列表,我该如何将它暴露给QML(在Qt5/QtQuick 2中)?似乎QML只能理解 - QObject派生类,这是一个问题,因为QObjects不能放入QList或复制.我该怎么做呢:
struct Thing
{
int size;
QString name;
};
class ThingManager : public QObject
{
Q_OBJECT
// These macros support QtQuick, in case we one day want to use it to make a slick
// interface (when QML desktop components are released).
Q_PROPERTY(QList<Thing> things READ things NOTIFY thingssChanged)
public:
// ...
QList<Thing> things() const;
// ...
};
Run Code Online (Sandbox Code Playgroud)
所以我可以在QML中做这样的事情:?
var a = thingManager.things[0].name;
Run Code Online (Sandbox Code Playgroud) 我的问题基本上是什么时候选择QVector以及何时选择QList作为你的Qt容器.我所知道的:
对于大多数用途,QList是正确的类.它的基于索引的API比QLinkedList的基于迭代器的API更方便,并且它通常比QVector更快,因为它将其项目存储在内存中.它还扩展到可执行文件中较少的代码.
这是非常受欢迎的问答:QVector vs QList.它也有利于QList.
但是:在最近的2015年Qt世界峰会上,KDAB提出了"为什么QList有害",这基本上是在这里:
不要使用QList,请使用Q_DECLARE_TYPEINFO
据我所知,这个想法是,QList在堆中分配新元素时,几乎所有类型都是低效的.每次添加新元素时,它都会调用new(每个元素一次),与之相比,这是低效的QVector.
这就是我现在试图理解的原因:QVector我们应该选择哪个默认容器?
Qt的容器类QList<T>,QVector<T>等需要它们的元素类型是可复制.从C++ 11开始,STL容器要求它们的元素类型只能是可复制的或可移动的.为什么Qt容器不支持仅移动元素类型?
我想保存一个QList<int>到我的QSettings而不循环它.
我知道我可以使用writeArray()和循环来保存所有项目或将QList写入QByteArray并保存它但是它在我的INI文件中不是人类可读的..
目前我正在使用以下内容将我转换QList<int>为QList<QVariant>:
QList<QVariant> variantList;
//Temp is the QList<int>
for (int i = 0; i < temp.size(); i++)
variantList.append(temp.at(i));
Run Code Online (Sandbox Code Playgroud)
要将其保存QList<Variant>到我的设置,我使用以下代码:
QVariant list;
list.setValue(variantList);
//saveSession is my QSettings object
saveSession.setValue("MyList", list);
Run Code Online (Sandbox Code Playgroud)
正如我所看到的那样,QList正确保存到我的INI文件中(我的整数的逗号分隔列表)
但该函数在退出时崩溃.
我已经尝试使用指向我的QSettings对象的指针,但是在删除指针时它会崩溃.
我只是注意到QList没有resize方法,QVector例如,有一个方法.为什么是这样?是否有相同的功能?
在我正在上课的课程中,我正在玩几个人QList.我听说Qt试图尽可能不制作列表的深层副本.据我所知,这意味着当你这样做时不会发生深层复制:
QList<int> myList;
myList << 1 << 2 << 3 << 4;
QList<int> otherList = myList; // No deep copy
Run Code Online (Sandbox Code Playgroud)
在某些情况下,我需要确保永远不会发生深层复制QList.我需要确保避免什么样的操作或操作才能确保QList我正在使用的深层拷贝永远不会发生?
我有一个QList指向具有类类型的对象的指针Model.我想QList在使用它后适当删除它.我知道Qt的理念是避免C风格的内存管理.我怎么delete这样QList?
我需要将类的指针(从QObject继承)插入到QList中.我知道可以使用以下语法:
.H
QList<MyObject*> list;
Run Code Online (Sandbox Code Playgroud)
的.cpp
list.append(new MyObject("first", 1));
list.append(new MyObject("second", 2));
...
Run Code Online (Sandbox Code Playgroud)
然后释放内存:
if(!list.isEmpty())
{
qDeleteAll(list);
list.clear();
}
Run Code Online (Sandbox Code Playgroud)
这应该是有效的,不会导致任何内存泄漏(据我所知).但是,我需要在将对象添加到集合之前初始化对象.以下代码段是否会导致内存泄漏或悬空指针等错误(我将使用相同的方法删除上面的指针)?
MyObject *obj;
for(i = 0; i < 5; i++)
{
obj = new MyObject();
if(!obj.Init(i, map.values(i)))
{
// handle error
}
else
{
list.append(obj);
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢.