目录
- 引出
- Qt遍历list提高效率
- 显示函数的调用
- 使用`&`与不使用`&`
- 除法的一个坑
- 总结
- 自定义信号和槽
- 1.自定义信号
- 2.自定义槽
- 3.建立连接
- 4.进行触发
- 自定义信号重载
- 带参数的
- 按钮触发
- 信号触发信号
- 拓展
- lambda表达式
- 返回值
- mutable修饰
- 案例
引出
QT学习积累——如何提高Qt遍历list的效率
Qt遍历list提高效率
在Qt中遍历QList
或其他容器时提高运算效率主要依赖于以下几点:
- 使用迭代器而非索引访问:对于
QList
和其他Qt容器类,使用迭代器进行遍历通常比使用索引访问元素更高效,特别是在非随机访问容器(如QList
对于大型对象)中。这是因为迭代器直接引用容器中的元素,而不是通过索引重新计算位置。
QList<int>::iterator it;
for (it = list.begin(); it != list.end(); ++it) {
// 使用 *it 访问元素
}
或者使用C++11的范围基于的for循环:
for (int &element : list) {
// 使用 element
}
避免不必要的对象复制:如果你的QList
包含的是自定义类型或大型对象,请确保在遍历时使用引用(或常量引用,如果你不需要修改它们),这样可以避免遍历过程中对象的不必要拷贝。
for (CustomType &item : list) {
// 使用 item
}
如果不需要修改元素,使用常量引用:
for (const CustomType &item : list) {
// 只读访问 item
}
考虑使用更合适的容器:QList
是一个非常通用的容器,但并不总是最高效的选择。如果你需要频繁地在序列中间插入或删除元素,可能会更倾向于使用QLinkedList
。如果元素经常被访问(特别是随机访问),则QVector
可能是更好的选择。选择最适合你需求的容器类型可以显著提高性能。
减少遍历次数:有时可以通过算法优化来减少对容器的遍历次数。例如,如果可能,尝试将多个操作合并到单个遍历中完成,而不是对同一个列表进行多次遍历。
使用Qt Concurrent进行并行处理:对于大型数据集和可以并行处理的任务,考虑使用Qt Concurrent模块中的函数,如QtConcurrent::map
,它可以自动地将任务分配到多个线程中执行,从而利用多核处理器的优势。
#include <QtConcurrent>
void processItem(int &item) {
// 对 item 进行处理
}
QList<int> list = ...;
QtConcurrent::map(list, processItem);
遵循这些指导原则可以帮助你在Qt应用程序中提高遍历QList
(以及其他容器)的运算效率。然而,请记住,性能优化应该是基于实际需要和通过分析确定的瓶颈来进行的。在许多情况下,代码的清晰性和可维护性比微小的性能提升更为重要。
显示函数的调用
使用&
与不使用&
在C++中,使用&
与不使用&
在for循环中会产生不同的行为:
- 使用
&
: 当在范围for循环(range-based for loop)中使用引用符号&
时,你将获得对容器内元素的直接引用。这意味着在循环内部对这些元素进行的任何修改都会反映到原始容器中的元素上。例如:
for (CircleData &ct : cList) {
ct.someProperty = newValue; // 这将修改cList中元素的属性
}
在这个例子中,任何对ct
的修改都会直接修改cList
中的对应CircleData
对象。
不使用 &
: 如果不使用引用符号,范围for循环将创建容器内每个元素的副本。在这种情况下,循环内部对副本所做的任何修改都不会影响原始容器中的元素。例如:
for (CircleData ct : cList) {
ct.someProperty = newValue; // 这只会修改副本的属性,并不会影响cList中的元素
}
在这个例子中,ct
是CircleData
对象的一个临时副本,对它的修改不会影响cList
中的原始对象。
总之,如果你打算修改循环中的元素,应当使用引用(&
),这将避免不必要的对象副本并确保修改作用于容器中的实际元素。如果你不需要修改元素或者只是想读取元素的数据,那么可以省略&
来避免潜在的副作用。然而,即使在只读情况下,为了避免不必要的拷贝操作,通常也会使用常量引用(const &
),如下:
for (const CircleData &ct : cList) {
// 只读取ct的数据,不进行修改
}
这样可以提高效率,特别是在处理大型对象时。
除法的一个坑
在C++(包括Qt)中,如果你执行整数除法(例如 1 / 2
),结果将是一个整数,因为操作数都是整数。这意味着结果会被截断,而不是四舍五入。因此,1 / 2
的结果将是 0
,而不是 0.5
。
如果你想得到 0.5
这个结果,你需要确保至少有一个操作数是浮点数。这可以通过将其中一个操作数显式转换为浮点数来实现,或者直接使用浮点数进行运算。
以下是在Qt中如何将 1 / 2
的结果用浮点数接收的示例:
#include <QDebug>
int main() {
// 方法1: 将其中一个操作数转换为浮点数
float result1 = static_cast<float>(1) / 2;
qDebug() << "Result 1:" << result1; // 输出: Result 1: 0.5
// 方法2: 直接使用浮点数进行运算
float result2 = 1.0f / 2.0f;
qDebug() << "Result 2:" << result2; // 输出: Result 2: 0.5
return 0;
}
在这两个示例中,我们都确保了除法运算至少有一个浮点数参与,这样结果就会是浮点数,而不是整数。这样,当你将结果赋值给一个浮点数变量时,你将得到正确的浮点数结果 0.5
。
总结
QT学习积累——如何提高Qt遍历list的效率
自定义信号和槽
1.自定义信号
写到signals下
返回void
需要声明,不需要实现
可以有参数,可以重戟
2.自定义槽
返回void
需要声明,也需要实现
可以有参数,可以重载
写到public slot下或者public或者全局函数
3.建立连接
// 老师饿了,学生请吃饭
connect(te,&Teacher::hungry,st,&Student::treat);
4.进行触发
自定义信号重载
当自定义信号和槽出现重载
8.1 需要利用还数指针明确指向函数的地址·
8.2void(Teacher::tsignal )QString )=&Teacher::hungry;
8.3 QString转成char *
8.3.1.ToUtf80转为QByteArray
8.3.2.Data0转为Char *
8.4信号可以连接信号
8.5断开信号disconnect
带参数的
void (Teacher::*teacherSignal)(QString) = &Teacher::hungry;
void (Student::*StudentSlot)(QString) = &Student::treat;
void Student::treat(QString foodName){
// QString -> char * 先转成QByteArray(.toUtf8()) 再转成Char* ()
qDebug() << "请老师吃。。。" << foodName.toUtf8().data();
}
按钮触发
// 用一个按钮调用下课
QPushButton *btn = new QPushButton("下课了",this);
// 重置窗口daxiao
this->resize(600,400);
connect(btn,&QPushButton::clicked,this,&Widget::classIsOver);
信号触发信号
// 无参的信号和槽连接
void (Teacher::*teacherSignal2)(void) = &Teacher::hungry;
void (Student::*StudentSlot2)(void) = &Student::treat;
connect(te,teacherSignal2,st,StudentSlot2);
// 信号连接信号
connect(btn,&QPushButton::clicked,te,teacherSignal2);
断开信号disconnect
拓展
1、信号是可以连接信号
2、一个信号可以连接多个槽函数
3、多个信号可以连接同一个糟函数
4、信号和槽函数的参数必须类型一一对应
5、信号和槽的参数个数是不是要一致?信号的参数个数可以多余槽函数的参数个数
connect(信号的发送者,发送的信号signal信号),信号接受者,槽函数SLOT)
优点:参数直观
缺点:编译器不会检测爸数类型:
lambda表达式
[=](){
btn->setText("aaa");
}();
返回值
int ret = []()->int{return 1000;}();
qDebug() << "ret = " << ret;
mutable修饰
QPushButton *myBtn1 = new QPushButton(this);
QPushButton *myBtn2 = new QPushButton(this);
myBtn1->move(100,100);
int m = 10;
connect(myBtn1,&QPushButton::clicked,this,
[m]()mutable {m=100+10;qDebug()<< m;});
connect(myBtn2,&QPushButton::clicked,this,
[=](){qDebug()<<m;});
qDebug() << m;
案例
QPushButton * btnClose = new QPushButton;
btnClose->setText("close");
btnClose->move(100,0);
btnClose->setParent(this);
connect(btnClose,&QPushButton::clicked,this,
[=](){
btnClose->setText("关闭");
emit te->hungry("娃哈哈");
// this->close();
});