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

QT 中使用 c++ 的指针的更多相关文章

  1. Qt中无处不在的d指针为何方神圣

    在研究QCoreApplication类的代码时,无意间弄明白了“d_func()”和“d指针”的来源: class Q_CORE_EXPORT QCoreApplication#ifndef QT_ ...

  2. Qt中窗口退出事件

    窗口右上角的X按键会导致其在不给出任何提示的情况下直接退出, 当点击右上角的x按键时,会触发Qt中的一个事件处理函数:void QWidget::closeEvent ( QCloseEvent * ...

  3. Qt中的ui指针和this指针

    初学qt,对其ui指针和this指针产生疑问,画了个把小时终于搞懂了. 首先看ui指针的定义: 在mainwindow.h中 private: Ui::MainWindow *ui; Ui又是什么? ...

  4. Qt中的Q_D宏和d指针

    _ZTS7QObject 一.Q_D的在文件中的提法 Q_D的设置意在方便地获取私有类指针,文件为qglobal.h.下面的##是宏定义的连字符.假设类名是A,那么A##Private翻译过来就是AP ...

  5. 智能指针类模板(中)——Qt中的智能指针

    Qt中的智能指针-QPointer .当其指向的对象被销毁时,它会被自动置空 .析构时不会自动销毁所指向的对象-QSharedPointer .引用计数型智能指针 .可以被自由的拷贝和赋值 .当引用计 ...

  6. PyQt(Python+Qt)学习随笔:Qt中的部分类型QString、QList和指针、引用在PyQt中的实现方式

    老猿Python博文目录 老猿Python博客地址 在我们查阅Qt的文档资料时,可以看到Qt中的链表使用的是QList,字符串使用的是QString,但老猿在测试时发现这两个类型PyQt不支持,无法找 ...

  7. Qt 中使用Singleton模式需小心

    在qt中,使用Singleton模式时一定要小心.因为Singleton模式中使用的是静态对象,静态对象是直到程序结束才被释放的,然而,一旦把该静态对象纳入了Qt的父子对象体系,就会导致不明确的行为. ...

  8. qt中ui的 使用介绍

    1.什么是ui?ui通常是用Qt 设计师设计出来的界面文件的后缀.通常情况下ui是一个指向这个界面类的指针.ui-> 一般就是用来访问这个界面类里面的控件.例如你的ui文件里有一个叫okButt ...

  9. Qt中sizeof

    class a{ int d; // virtual void ssss(); }; qDebug() <<sizeof(a) << sizeof(int) << ...

随机推荐

  1. Canvas get/putImageData

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. 基于Ubuntu 14.04构建tomcat7镜像

    1.创建Dockerfile文件(如果在Windows下编辑文件,一定要将格式转化为Linux格式文件,否则将导致Linux下查看文件每行多一个^M) # Pull base image FROM u ...

  3. HDU5477(模拟)

    A Sweet Journey Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  4. 利用canvas制作乱跑的小球

    canvas制作乱跑的小球 说明:将下面的代码放到html的body就可以,键盘控制上(W)下(S)左(A)右(D) <body> <canvas id="canvas&q ...

  5. struts2系列笔记(1)

    struts2框架 如果你之前在MVC模式的时候一直都是通过servlet,获取和返回数据,那么现在开始学习struts2框架, Struts是一个实现MVC设计模式的优秀的框架.它的许多优点我就不说 ...

  6. 从C#到TypeScript - 类

    总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...

  7. JavaScript 事件总结

    本文总结自<JavaScript高级程序设计>以及自己平时的经验,针对较新浏览器以及 DOM3 级事件标准(2016年8月),对少部分内容作了更正,增加了各种例子及解析. 如无特殊说明,本 ...

  8. 阿里巴巴Java开发手册———个人追加的见解和补充(一)

    先上干货,<阿里巴巴Java开发手册>的下载地址 https://yq.aliyun.com/articles/69327?spm=5176.100239.blogcont69327.15 ...

  9. (@WhiteTaken)设计模式学习——建造者模式

    Builder模式,也就是建造者模式或者生成器模式,是GoF提出的23种设计模式的一种. 这种模式是用来隐式的创建复合对象而提出来的. 创建复合对象的过程,不在主客户端显示. 下面直接上代码.以修建房 ...

  10. android学习1——LinearLayout

    用linearLayout,上面放4个按钮,不作任何设置.xml文件内容如下: <?xml version="1.0" encoding="utf-8"? ...