博客
关于我
数据结构 第26课 典型问题分析(Bugfix)-------1----------狄泰软件学院
阅读量:261 次
发布时间:2019-03-01

本文共 5500 字,大约阅读时间需要 18 分钟。

文章目录

问题1 (深入分析 strdup )

#include 
#include "Exception.h"using namespace std;using namespace DTLib;int main(){ try { NullPointerException npe; // 会调用父类的构造函数 cout << "throw" << endl; throw npe; } catch(const exception& e) { cout << "catch" << endl; } return 0;}/*结果: throw terminate called after throwing an instance of 'DTLib::NullPointerException' 至于为啥报错,我也不清楚;;;;;;;;;;;;;;本不应报错 示例程序过于短小,说明不了什么问题,要深入标准C库一探究竟; 在glibc 中查strdup 函数 结果: glibc 中的 strdup 函数的函数参数是 默认认为字符串不为空的, 但是我们如果如上图那样定义异常对象,相当于调用strdup(0)。 在异常类中,不判断message是否为空,是有问题的 在Exception.h中,一句话经历的改变 //m_message = message; // 参数指针指向的字符串位置未知,这样无法控制外部字符串的生命周期,这种写法是不安全的, 处理方法: 拷贝一份字符串出来 //m_message = strdup(message);// 字符串的复制 到堆空间,这时 m_message 指向堆空间中的字符串 m_message = (message ? strdup(message) : NULL); // 这样的代码才足够安全 通过glibc的strdup形成方式,增强代码健壮性的方法就是这样改。*/

问题2 (链表逻辑,异常安全性)

#include 
#include "LinkList.h"using namespace std;using namespace DTLib;class Test : public Object{ int m_id;public: Test(int id = 0) { m_id = id; } ~Test() { if( m_id == 1 ) { throw m_id; } }};int main(){ LinkList
list; Test t0(0), t1(1), t2(2); try { list.insert(t0); list.insert(t1); list.insert(t2); list.remove(1); } catch(int e) { cout << e << endl; cout << list.length() << endl; } return 0;}/* 出现的问题:Qt 编译器直接崩溃,VS 编译器也直接崩溃,因为析构函数中不能抛出异常。但是VS 编译器输出了 1 和 3。按理说我们移除了一个元素,为什么编译器长输出的长度还是3而不是2呢?这说明了remove()函数没有考虑异常安全性再LinkList中,remove函数 m_length--; destroy(toDel); //应该全部完成再销毁 clear() 函数改成: void clear() { while(m_header.next != nullptr) { Node* toDel = m_header.next; m_header.next = toDel->next; m_length--; destroy(toDel); } }*/

问题3 ( LinkList 中遍历操作与删除操作的混合使用)

#include 
#include "LinkList.h"using namespace std;using namespace DTLib;int main(){ LinkList
list; for(int i = 0; i < 5; i++) { list.insert(i); } for(list.move(0); !list.end(); list.next()) { if(list.current() == 3) { list.remove(list.current()); cout << list.current() << endl; } } for(list.move(0); !list.end(); list.next()) { cout << list.current() << endl; } return 0;}/*出现的问题: 出现随机值问题原因:链表被删除后,m_current 依旧指向了原来的内存解决方案:我们可以把m_current 指向下一个内存。bool remove(int i){ bool ret = ((0 <= i) && (i <= m_length)); if(ret) { Node* current = position(i); Node* toDel = current->next; if(m_current == toDel) // 判断m_current是否指向了即将被删除的元素 { m_current = toDel->next; //m_current 指向即将被删除的下一个元素(因为这一块元素要被删除掉了,没有这一步骤,会出现随机值) } current->next = toDel->next; // 链接 m_length--; destroy(toDel); } return ret;}*/

问题4(StaticLinkList 中数据元素删除时的效率问题)

/*这里的最终结果依然出现了问题,最后仅得到一个 0 值。*/#include 
#include "StaticLinkList.h"using namespace std;using namespace DTLib;int main(){ StaticLinkList
list; for(int i=0; i<5; i++) { list.insert(i); } list.remove(3); // 会调用到 destroy()里去; for(int i=0; i
(m_space); // 要做指针运算,所以要做强制类型转换 SNode* pst = dynamic_cast
(pn); // 从父类指针转换到子类指针 for(int i=0; i
~SNode(); // 析构 break; // 归还了就可以跳出循环了,没有必要继续循环下去,虽然在循环下去月不可能走进if语句了,数据结构为了高效*/ } } }

问题5 (非常经典的问题)

#include 
#include "LinkList.h"#include "StaticLinkList.h"using namespace std;using namespace DTLib;int main(){ StaticLinkList
list; for(int i = 0; i < 5; i++) { list.insert(i); } for(int i = 0; i < 5; i++) { cout << list.get(i) << endl; }}// 这个子类对象被析构的时候,会调用父类的析构函数,,父类delete的内存空间来自子类所创建的空间,// 最终delete的就不是堆空间了,就会造成系统不稳定,程序什么时间会崩溃是无法预测的/*是否提供析构函数由资源来决定,申请了资源就要归还(析构)StaticLinkList.h 在构造函数中没有申请系统资源, 从资源的角度,就没有必要提供析构函数了;(有一个前提条件,所实现的类是一个单独的类,没有任何继承关系,)但,是否提供唯一的析构函数,不能以唯一的准则来判断打开所继承的LinkList类, LinkList提供了析构函数,并且在析构函数中调用了虚函数,但是,多态是不会发生的构造函数和析构函数中是不会发生多态的,,,所以,不管在哪里调用,都是唯一的版本,仔细分析,clear()中又调用了 destory()虚函数,而 destory()在父类中一个版本,在子类中又实现一个版本意味着,父类的析构函数被调用的时候,始终调用的destory() 都是父类中的destory(),子类的destory()是没有办法在析构的时候被调用到的,构造函数和析构函数中是不会发生多态的,,不管你是直接调用的虚函数还是间接调用的虚函数,都是当前类中所实现的那个虚函数解决方案:在子类中添加自己的析构版本,~StaticLinkList(){ this->clear();}调用的是父类的clear函数,clear函数调用destory(),就是当前类中的实现构造函数和析构函数是不会发生多态的,所调用的虚函数,都是当前类中的实现版本,不管是直接调用还是间接调用;*/

问题6(DTLib 是否有必要增加多维数组类?)

#include 
#include "StaticLinkList.h"#include "DynamicArray.h"using namespace std;using namespace DTLib;/*— DTLib 是否有必要增加多维数组类?答:没必要,因为多维数组的本质:数组的数组如果你想得到一个二维数组对象,可以这样做:来构造不规则的二维数组;;;*/int main(){ DynamicArray< DynamicArray
> d; // d 是一个对象,具体类型是一个数组,保存的元素是另一个数组 《二维》 d.resize(3); // 第一维数组 3行 for(int i = 0; i < d.length();i++) // 确定每一行的元素 { d[i].resize(i + 1); // 第0数组 有一个元素, 第2数组,又两个元素~~ } for(int i = 0; i < d.length();i++) { for(int j = 0; j < d[i].length(); j++) { d[i][j] = i * j; } } for(int i = 0; i < d.length();i++) { for(int j = 0; j < d[i].length(); j++) { cout << d[i][j] << " "; } cout << endl; } return 0;}

转载地址:http://wcux.baihongyu.com/

你可能感兴趣的文章
Mysql order by与limit混用陷阱
查看>>
Mysql order by与limit混用陷阱
查看>>
mysql order by多个字段排序
查看>>
MySQL Order By实现原理分析和Filesort优化
查看>>
mysql problems
查看>>
mysql replace first,MySQL中处理各种重复的一些方法
查看>>
MySQL replace函数替换字符串语句的用法(mysql字符串替换)
查看>>
mysql replace用法
查看>>
Mysql Row_Format 参数讲解
查看>>
mysql select, from ,join ,on ,where groupby,having ,order by limit的执行顺序和书写顺序
查看>>
MySQL Server 5.5安装记录
查看>>
mysql server has gone away
查看>>
mysql slave 停了_slave 停止。求解决方法
查看>>
MySQL SQL 优化指南:主键、ORDER BY、GROUP BY 和 UPDATE 优化详解
查看>>
MYSQL sql语句针对数据记录时间范围查询的效率对比
查看>>
mysql sum 没返回,如果没有找到任何值,我如何在MySQL中获得SUM函数以返回'0'?
查看>>
mysql Timestamp时间隔了8小时
查看>>
Mysql tinyint(1)与tinyint(4)的区别
查看>>
mysql union orderby 无效
查看>>
mysql v$session_Oracle 进程查看v$session
查看>>