博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
homework-08
阅读量:5950 次
发布时间:2019-06-19

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

上次作业中,已经提到了C++ 11的特性。不过,光说不练假把式,这次作业中,我们就对此进行验证。

 

进行测试的4个项目分别为:

1.变量作用域和生命周期

2.堆和栈

3.unique_ptr和shared_ptr

4.分割url

 

为了保证测试的有效性,先要检测编译器对于C++ 11的支持情况。以下是目前主流编译器的支持情况:

 

由于Clang编译器对于C++ 11的支持比较不错,所以本次我们就选择了Clang作为编译环境

 

从中我们可以看到,编译器是3.3版本,支持本次我们需要用到的所有特性。

 

1.变量作用域和生命周期

这个测试主要是让我们理解变量作用域的概念,所以我们可以使用如下代码:

int main(){    int v = 1;    cout << "In level 1: v=" << v << endl;    {        int v = 2;        cout << "In level 2: v=" << v << endl;    }    cout << "Back to level 1: v=" << v << endl;    return 0;}

main第一层的v只管第一层,第二层的v只管第二层,第二层的v不会影响到第一层的。如图所示:

 

运行结果如下:

 

与上述解释相符。

 

2.堆和栈

堆和栈是一个容易上新手感到困惑的概念。其实很简单,只要这样理解:栈空间会自动消失,堆空间如果不释放,就不会消失。就类似第一个问题里面,栈的变量都是局部变量,出了那个局部,变量就消失了。比如如下代码:

#include 
using namespace std;int *getValueInStack(){ int *v; *v=9210; return v;}int *getValueInHeap(){ int *v; v = new int; *v=9210; return v;}int main(){ cout << "In heap: v=" << *getValueInStack() << endl; cout << "In stack: v=" << *getValueInHeap() << endl; return 0;}

getValueInStack是从栈里面获得一个变量

getValueInHeap是从堆里面获得一个变量

现在的编译器已经十分智能了,帮我们发现了这个错误,并给出了警告。如果我们不管这个警告,继续执行的话,就会产生非法访存的段错误:

但是,当我把main()函数里两句话换一下位置以后,再加上点修改,就产生了奇妙的现象:程序能输出一个结果,不过非常诡异。

#include 
using namespace std;int *getValueInStack(){ int *v; *v=9210; cout << "In getValue(): v=" << *v << endl; return v;}int *getValueInHeap(){ int *v; v = new int; *v=9210; cout << "In getValue(): v=" << *v << endl; return v;}int main(){ cout << "In heap: v=" << *getValueInHeap() << endl; cout << "In stack: v=" << *getValueInStack() << endl; return 0;}

这段代码是在我输入错误的时候打进去的,可是却能神奇的输出结果。对于这个奇妙的现象,我在Windows 8.1(编译环境Visual Studio 2013)和Mac(Clang & LLVM 3.3)下都进行了测试。居然是不一样的,windows下这里会报错。

 

由于这个错误,我猜测Windows和Mac有着微妙的差别:Windows编译器对参数是从右往左解析的,Mac是从左往右的。所以Mac在执行getValueInStack之前已经输出了"In stack:"字符串,所以getValueInStack返回的地址的空间先前已经被字符串指针申请过了,所以不会报错。而windows是从右向左的,执行函数之前,那片空间还没有被申请,所以就产生了非法访问。

 

3.unique_ptr和shared_ptr

 

这个真的是一个激动人心的想法,本来C语言的内存泄漏问题就比较严重,有了这个以后就可以在很大程度上避免这个问题。

 

先说unique_ptr,这个的意义就在于一块空间只能有一个指针指向它。下面一张图表示了一个空间指针的交接:

 

unique_ptr是不能直接传值的,比如如下代码在编译时就会直接报错:

#include 
#include
using namespace std;int main(){ std::unique_ptr
p1(new int(5)); std::unique_ptr
p2=p1; return 0;}

为了实现这个转移功能,我们就需要修改代码:

#include 
#include
using namespace std;int main(){ std::shared_ptr
p1(new int(5)); std::shared_ptr
p2 = p1; cout << *p1 << endl; cout << *p2 << endl; return 0;}

move()函数进行了交接操作,p1内存归p2所有,p1变成无效指针,运行起来能输出p1,输出p2就会产生错误

然后就顺利完成了

 

unique_ptr的意义在于,有效防止了指针悬挂,以及由此引起的非法访问操作。

 

shared_ptr

感觉这个就像个超级保姆,有效避免了内存泄漏。

#include 
#include
using namespace std;int main(){ std::shared_ptr
p1(new int(5)); std::shared_ptr
p2 = p1; cout << *p1 << endl; cout << *p2 << endl; return 0;}

shared_ptr的意义在于,统一管理了指针的分配,在没有指针指向空间的时候立即释放空间,很大程度上避免了内存泄漏。

 

4.url分割

要求:

1. 类的定义和使用,基本成员是否完整

2. 输入参数的检查及其他鲁棒性的考虑

3. STL和C++11元素的使用

4. 除http://之外, 是否有考虑ftp:// site:// 等情况

5. 是否考虑url中的中文

6. 算法是否简洁高效

7. 代码风格

 

 C语言实现

我的代码做到了

绝对robust,保证不会有溢出,哪怕100W的字符进来也不会

对于所有符号通吃

url中文也毫无压力

算法是O(1)复杂度

代码风格规范

#include 
#define isChar(x) (x>='a'&&x<='z'||x>='A'&&x<='Z'||x>='0'&&x<='9'||x=='-'||x<0)int main(){ char c; int inWord = 1; while ((c=getchar())!='\n') { if (isChar(c)) { inWord = 1; printf("%c", c); } else if (inWord) { printf(", "); inWord = 0; } } printf("\n"); return 0;}

中文的实现主要在于字符的判断

以上的代码十分简单,但是有个小问题,不支持"://"的判断,不过不要紧,稍加改动就可以:

#include 
#define isChar(x) (x>='a'&&x<='z'||x>='A'&&x<='Z'||x>='0'&&x<='9'||x=='-'||x<0)int main(){ char c; int inWord = 1, readHead = 0; while ((c=getchar())!='\n') { if (isChar(c)) { inWord = 1; printf("%c", c); } else if (inWord) { printf(", "); if (!readHead) { if (c != ':') break; if (getchar() != '/') break; if (getchar() != '/') break; readHead = 1; } else { inWord = 0; } } } if (!readHead) { printf("\rNot a valid URL!"); } printf("\n"); return 0;}

 

 

经过这样的修改,程序就具有了超强的鲁棒性完全不怕数据溢出,哪怕几千万个字节的输入也都可以分割。

程序也有了超强的性能内存占用几乎为0,可以以超高的吞吐量处理流数据

中文的支持,统统能够分割。

简洁的代码

url完整性检查

最后,还有跨平台(Windows和OS X),跨编码集的(GBK与UTF-8)支持:

C++代码(使用STL):

#include 
#include
#include
#define isChar(x) (x>='a'&&x<='z'||x>='A'&&x<='Z'||x>='0'&&x<='9'||x=='-'||x<0)using namespace std;vector
split(string s){ int i = 0, begin, inWord = 0; vector
ret; for (i=0;i
v = split(s); if (v.size() > 0) { cout << v[0]; } for (i=1;i

使用了两个类,一个是srting,另一个vector。先判断是否有字串”://”,然后就进行分割操作即可。分割的结果存入STL提供的vector中。

 

转载于:https://www.cnblogs.com/yzong/p/3428632.html

你可能感兴趣的文章
【翻译】如何在Ext JS 6中使用Fashion美化应用程序
查看>>
(转载)浅谈javascript中的原型和继承
查看>>
删除存储
查看>>
suffix
查看>>
[十一]基础数据类型之Character
查看>>
webpack+vue自学(2)
查看>>
mysqldump 备份导出数据排除某张表或多张表
查看>>
鼠标滑动一定距离的左侧菜单置顶效果
查看>>
Helloworld模块之内核makefile详解
查看>>
Exchange企业实战技巧(12)通讯组管理
查看>>
linux文件系统安全
查看>>
R语言执行脚本的几种命令
查看>>
bash之正则表达式
查看>>
MySQL5.7 Read Committed事务隔离级别的研究-出现幻读
查看>>
VUE的数据双向绑定
查看>>
轻量级HTTP服务器Nginx(配置与调试Nginx)
查看>>
解决CentOS系统mini安装后的虚拟机工具(VMware Tools)安装问题
查看>>
碧海蓝天的初心
查看>>
6.30Java学习第二天
查看>>
Ubuntu学习笔记
查看>>