QT中使用C++的指针
作者:网络转载 发布时间:[ 2016/11/7 10:52:21 ] 推荐标签:指针 QT 函数
之前没有接触过 c++,不过听说 c++ 的指针很坑,直到近在用 QT / C++ 写一个 Linux Deepin 系统上检测网络流量和网速的小程序时,发现 c++ 的指针用起来真的特别蛋疼。
不过好在花了几个小时终还是明白了指针的用法。
有一段代码的原型大概是这样的:
QList<NetFlowObject> netflowobj_list;
/** 从 list 列表中找出网卡名为 ifname 的 NetFlowObject 对象 **/
bool getNfoFromList(QString ifname, NetFlowObject &nfo);
其中 NetFlowObject 是自己写的一个类,QList 是 Qt 提供的一个链表。 getNfoFromList 函数返回 boolean 型结果,如果找到相同名称的网卡,返回 true,并将 nfo 设为 QList 中找到的 NetFlowObject 对象。否则返回 false。
那么开始的想法是通过遍历 QList 找到 NetFlowObject 对象。
bool NetInfo::getNfoFromList(QString ifname,NetFlowObject &nfo) { //-------- A① foreach(NetFlowObject o, netflowobj_list) { //-------- A② if(o.getIfName() == ifname) { //-------- A③ nfo = o; return true; } } return false; }
void NetInfo::someFunction() {
// 如果找到相同的 nfo 对象,修改它的数据
NetFlowObject nfo1;
bool finded = getNfoFromList(ifname, nfo1); //-------- B①
if(finded) {
nfo1.updateRecvBytes(if_recv_bytes.toInt());
nfo1.updateTransBytes(if_trans_bytes.toInt());
}
}
嗯,上面的这段代码很显然没有办法修改 QList 链表中的对象的属性。首先,函数是传值的,也是说 A① 处函数的参数 nfo 是不会影响 someFunction 里 B① 处的 nfo1 对象的。nfo1 对象的属性改变同样也不会影响 nfo 对象。
通过函数的参数传递的只是 nfo1 对象的一个副本,两个对象之间不会影响。
其次,A②处的 foreach 这个便捷的循环也是提供 QList 对象的一个副本,这样的话,更加没有办法修改找到的 NetFlowObject 对象了。
好吧,这个错误是 c++ 常见也是愚蠢的错误,那么想要得到 QList 中的某个 NetFlowObject 对象的引用,函数传递的不能是 NetFlowObject 对象了,那么改成 NetFlowObject * 也是指针吧。另外,将循环改为 for 计数循环。
代码如下
bool NetInfo::getNfoFromList(QString ifname,NetFlowObject *nfo) {
for(int i = 0; i < netflowobj_list.count(); i++) {
NetFlowObject o = netflowobj_list[i];
// PrintUtil::print(o.getIfName() + " === " + QString::number(o.getLatestRecvBytes()));
if(o.getIfName() == ifname) {
*nfo = netflowobj_list[i]; // 将指针所指向的 NetFlowObject 对象修改为 o -------C①
return true;
}
}
return false;
}
相应的,
bool finded = getNfoFromList(ifname, &nfo1);
但是这样做,发现修改 nfo1 对象仍然没有效果, QList 中 NetFlowObject 对象的属性依然没有改变。恩没有错,上面代码 C① 处又是传递的副本。
这里要说一下 QList 对象的 at(i) 函数和 QList[i] 数组形式得到的对象是不同的。函数原型为 const T &QList.at(int i) const,也是不能通过 at() 的返回值对 nfo 对象进行修改,
而数组形式的函数原型是 T &QList::operator[] (int i),也是用起来和平常的数组没什么太大区别。
既然一层引用不能达到效果,那么,函数传递的时候,传一个 NetFlowObject * 对象的指针,也是作为 NetFlowObject 对象的指针的引用。(这个指针的指针说起来太绕口了,第二个指针改称引用,不然脑子浆糊了),贴出终的代码:
bool NetInfo::getNfoFromList(QString ifname,NetFlowObject **nfo) {
for(int i = 0; i < netflowobj_list.count(); i++) {
NetFlowObject o = netflowobj_list[i];
// PrintUtil::print(o.getIfName() + " === " + QString::number(o.getLatestRecvBytes()));
if(o.getIfName() == ifname) {
*nfo = &netflowobj_list[i]; // 将指针所指向的 NetFlowObject 指针修改为 QList 中第 i 个对象的引用
return true;
}
}
return false;
}
void NetInfo::someFunction() {
NetFlowObject *nfo;
bool finded = getNfoFromList(ifname, &nfo);
if(finded) {
nfo->updateRecvBytes(if_recv_bytes.toInt());
nfo->updateTransBytes(if_trans_bytes.toInt());
}
}
通过两层引用,终达到了修改 QList 链表中对象的目的。
感觉还有一种解决方法,是将函数原型 getNfoFromList 修改成 NetFlowObject * getNfroFromList(QString ifname);
找到相应的对象后直接返回该对象的引用,这样不用通过函数参数传递两层引用了。
-------------------------- 思考 -------------------------
引用指针绕的头都晕了,而且这个错误理论上应该属于逻辑错误(编译时不会报错,运行时不会发生异常),但是特喵的是结果不对,debug 起来也很蛋疼,通过长时间的分析和总结才能得到正确的结果。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11