之前没有接触过 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. Linux内存管理之slab分配器

    slab分配器是什么? 参考:http://blog.csdn.net/vanbreaker/article/details/7664296 slab分配器是Linux内存管理中非常重要和复杂的一部分 ...

  2. vue初探

    vue初探 很多同学一定都听过MVVM.组件.数据绑定之类的专业术语,而vue框架正是这样的一种框架.vue的作用是:通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件. 第一部分:vue介 ...

  3. node源码详解(五) —— 在main函数之前 —— js和C++的边界,process.binding

    本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource5 本博客同步在https://cnodejs.o ...

  4. tomcat服务器搭建之ngrok——将内网地址映射到外网

    最近心血来潮,想学习微信公众号开发.但是自己又没有外网服务器,这个给我带来很大的麻烦. 刚开始申请了新浪云服务和百度云服务,将写好的代码打包丢到相应的云服务器上就行. 但问题就来了,开发中避免不了错误 ...

  5. Linux上使用shell脚本查看内存情况(超实用)

    #!/bin/bashexport chknum=1 #shell搅拌存放目录(输出日志文件执行后也存于该目录)echo 3 > /wls/wls81/shellsyncwhile [ $chk ...

  6. js中的 arguments ,实参的集合

    当 传递的参数个数不确定时,,可使用 arguments ..

  7. LinQ 创建连接、简单增删改查

    LINQ--语言集成查询(Language Integrated Query)是一组用于c#和Visual Basic语言的扩展.它允许编写C#或者Visual Basic代码以查询数据库相同的方式操 ...

  8. AFNetworking2.0和AFNetworking3.0 的HTTPS的配置

    前言: 由于苹果声明在前说是2017.01.01之后提交审核的APP,必须使用HTTPS请求,要不就直接驳回审核,吓得我们年前赶紧提交了一个版本,想着年后在弄这个https,结果又有消息说是苹果推迟了 ...

  9. make: Nothing to be done for `all'

    最近安装fastdfs,执行make.sh时,出现  Nothing to be done for `all' 在网上搜了一下,大部分是说 用 make clean 清除以前编译产生的目标文件. 我试 ...

  10. Angularjs学习笔记《一》

    开始慢慢的学习新的框架,Angularjs,其中原理不知深浅,但有例子练习,慢慢熟知.看的英文文档一点点翻译学习. 第一个例子,写一个增加,选中,删除的例子, 首先要引进所用的框架源码,这样引进,下面 ...