之前没有接触过 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 起来也很蛋疼,通过长时间的分析和总结才能得到正确的结果。

转载于:https://www.cnblogs.com/brifuture/p/6037485.html

QT 中使用 c++ 的指针相关推荐

  1. Qt中的d指针和q指针

    概述 如果程序从一个以前版本的库动态链接到新版本的库之后,能够继续正常运行,而不需要重新编译,那么我们就说这个库是二进制兼容的. 如果一个程序需要重新编译来运行一个新版本的库,但是不需要对程序的源代码 ...

  2. QT中的D指针与Q指针

    了解QT中引入D指针的初衷前需要了解下二进制兼容 1. 什么是二进制兼容 二进制兼容是针对动态链接库而言的,如果你的源代码已经编译成为可执行文件了,其中你调用了一些动态库,后来你为这个动态库进行了更新 ...

  3. Qt中的模型视图设计模式

    文章目录 1 初探Qt中的模型视图设计模式 2 模型视图中的索引 3 模型中的数据组织方式初探 1 初探Qt中的模型视图设计模式 模型视图设计模式的核心思想: 模型(数据)与视图(显示)相分离. 模型 ...

  4. Qt中内存泄露和半自动内存管理

    Qt中帮程序员做了一些内存回收的事情,但正因为这些反而让对此不熟悉的人会屡屡犯错. 收录一篇不错的文章: 在C++中学习过程中,我们都知道: delete 和 new 必须 配对使用(一 一对应):d ...

  5. Qt 中容器类型的控件

    转载:https://subingwen.cn/qt/qt-containers/ 1.QWidget 这个类是所有窗口类的父类,可以作为独立窗口使用,也可以内嵌到其它窗口中使用. Qt 中的所有控件 ...

  6. Qt中Ui名字空间以及setupUi函数的原理和实现

    Qt中Ui名字空间以及setupUi函数的原理和实现 分类: Qt GUI 2012-03-08 15:38 10514人阅读 评论(4) 收藏 举报 uiqtsignalclassdelete 用最 ...

  7. 4.关于QT中的QFile文件操作,QBuffer,Label上添加QPixmap,QByteArray和QString之间的区别,QTextStream和QDataStream的区别,QT内存映射(

     新建项目13IO 13IO.pro HEADERS += \ MyWidget.h SOURCES += \ MyWidget.cpp QT += gui widgets network CON ...

  8. 【Qt】Qt中信号与槽

    00. 目录 文章目录 00. 目录 01. 信号与槽 02. 介绍 03. 信号与槽 04. 信号 05. 槽 06. 一个小例子 07. 一个真实的例子 08. 信号和槽使用默认参数 09. 信号 ...

  9. 用事件队列解决GUI的操作顺序问题(Qt中处理方法)

    GUI操作顺序问题引发异常: 有时候我们使用写GUI程序的时候会遇到这样的问题:比如在程序中,建立了一个列表的GUI.这个列表是随着时间不断更新的,而且操作也会读取这个列表GUI的内容. 如果这个程序 ...

最新文章

  1. 这本空降京东当当新书榜TOP1的“算法小抄”是什么来头?
  2. Base64编码算法
  3. java怎么缓存行填充_为什么java的Exchanger.Slot缓存行填充像这样?
  4. UGUI- 单列列表(VerticalLayoutGroup)
  5. 开发环境运行正常,发布服务器后提示HTTP 错误 403.14 - Forbidden
  6. day10-函数基础总结
  7. Direcshow中视频捕捉和参数设置报告
  8. 创建与维护MySQL数据库
  9. 高德地图开放平台概览
  10. 《客户反映访问公司网站服务器很慢或打不开》排错思想
  11. csp m2 HRZ学英语
  12. loadrunner中关联到的信息需要拼接时的例子-订飞机票
  13. Window10系统下触摸板失灵了 该咋处理
  14. java graphics画圆_在Java中绘制一个漂亮的圆圈
  15. 免费的ipad编辑php软件下载,免费也很香!8 款免费 APP 打造你的学术型 iPad
  16. Webview--如何让加载进来的页面自适应手机屏幕分辨率
  17. 1月重磅福利——Softing在线培训课程上线
  18. 【XSY3126】异或II 数学
  19. 数据仓库和数据集市的概念、区别与联系
  20. 【更新】【Windows Server 2019】存储服务器的配置和管理——iSCSI的安装和配置(上)

热门文章

  1. 学习笔记Flink(五)—— Flink开发环境配置及运行实例(单词计数)
  2. pemicro识别不了驱动_usb驱动无法识别如何解决,手把手教你如何解决usb驱动问题...
  3. 2021-01-10 Halcon初学者知识 【9】形状匹配【一】准备图像
  4. jquery post 返回php,如何在成功的AJAX / jQuery POST上返回PHP变量
  5. 跨境电商自建站后台系统原型rp_没学历做跨境电商好做吗?虾皮shopee开店没有流水怎么办...
  6. Vue中bus的使用
  7. tensorflow只用CPU运行
  8. Python stylecloud制作酷炫的词云图
  9. CSS学习04之层次选择器
  10. VS调用matlab