仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 3044|回复: 8
打印 上一主题 下一主题

[C++基础] 给大家带来C++言语的15个流畅特征

[复制链接]
只想知道 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-16 11:05:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
看不懂man文档的人.在linux中,命令可分为系统基本命令和应用程序命令.系统基本命令是所有的unix类系统都支持的命令,走到哪都不变,只要是unix类系统上就肯定有.
  这个列表搜集了C++言语的一些流畅(Obscure)特征,是我经年累月研讨这门言语的各个方面搜集起来的。C++十分复杂,我老是能学到一些新常识。即便你对C++已洞若观火,也但愿你能从列表中学到一些器材。上面枚举的特征,依据流畅水平由浅进深举行排序。





  • 1.方括号的真正寄义
  • 2.最烦人的剖析
  • 3.替换运算标志符
  • 4.重界说关头字
  • 5.Placementnew
  • 6.在声明变量的同时举行分支
  • 7.成员函数的援用润色符
  • 8.转向完全的模板元编程
  • 9.指向成员的指针操纵符
  • 10.静态实例办法
  • 11.重载++和–
  • 12.操纵符重载和反省按次
  • 13.函数作为模板参数
  • 14.模板的参数也是模板
  • 15.try块作为函数
  方括号的真正寄义

  用来会见数组元素的ptr[3]实在只是*(ptr+3)的缩写,与用*(3+ptr)是等价的,因而反过去与3[ptr]也是等价的,利用3[ptr]是完整无效的代码。
  最烦人的剖析

  “mostvexingparse”这个词是由ScottMeyers提出来的,由于C++语法声明的二义性会招致有悖常理的举动:
  1. //这个注释准确?//1)范例std::string的变量会经由过程std::string()实例化吗?//2)一个函数声明,前往一个std::string值并有一个函数指针参数,//该函数也前往一个std::string但没有参数?std::stringfoo(std::string());//仍是这个准确?//1)范例int变量会经由过程int(x)实例化吗?//2)一个函数声明,前往一个int值并有一个参数,//该参数是一个名为x的int型变量吗?intbar(int(x));
复制代码
  两种情况下C++尺度请求的是第二种注释,即便第一种注释看起来更直不雅。程序员能够经由过程包抄括号中变量的初始值来打消歧义:
  1. //加括号打消歧义std::stringfoo((std::string()));intbar((int(x)));
复制代码
  第二种情况让人发生二义性的缘故原由是inty=3;等价于int(y)=3;
  译者注:这一点我以为有点利诱,上面是我在g++下的测试用例:
  1. #include<iostream>#include<string>usingnamespacestd;intbar(int(x));//等价于intbar(intx)stringfoo(string());//等价于stringfoo(string(*)())stringtest(){return"test";}intmain(){cout<<bar(2)<<endl;//输入2cout<<foo(test);//输入testreturn0;}intbar(int(x)){returnx;}stringfoo(string(*fun)()){return(*fun)();}
复制代码
  能准确输入,但假如按作者意义增加上括号后再编译就会报一堆毛病:“在此感化域还没有声明”、“重界说”等,还不分明作者的企图。
  替换运算标志符

  标志符and,and_eq,bitand,bitor,compl,not,not_eq,or,or_eq,xor,xor_eq,<%,%>,<:和:>都能够用来取代我们经常使用的&&,&=,&,|,~,!,!=,||,|=,^,^=,{,},[和]。在键盘上缺少需要的标记时你可使用这些运算标志符来取代。
  重界说关头字

  经由过程预处置重视界说关头字从手艺上讲会引发毛病,但实践上是同意如许做的。因而你可使用相似#definetruefalse或#defineelse来弄点开玩笑。可是,也有它正当有效的时分,比方,假如你正在利用一个很年夜的库并且必要绕过C++会见回护机制,除给库打补钉的办法外,你也能够在包括该库头文件之前封闭会见回护来办理,但要记得在包括库头文件以后必定要翻开回护机制!
  1. #defineclassstruct#defineprivatepublic#defineprotectedpublic#include"library.h"#undefclass#undefprivate#undefprotected
复制代码
  注重这类体例不是每次都无效,跟你的编译器有关。当实例变量没有被会见把持符润色时,C++只必要将这些实例变量按次结构便可,以是编译器能够对会见把持符组从头排序来自在变动内存结构。比方,同意编译器挪动一切的公有成员放到私有成员的前面。另外一个潜伏的成绩是称号重整(namemangling),Microsoft的C++编译器将会见把持切合并到它们的namemangling内外,因而改动会见把持符意味着将损坏现有编译代码的兼容性。
  译者注:在C++中,NameMangling是为了撑持重载而到场的一项手艺。编译器将方针源文件中的名字举行调剂,如许在方针文件标记表中和毗连过程当中利用的名字和编译方针文件的源程序中的名字纷歧样,从而完成重载。
  Placementnew

  Placementnew是new操纵符的一个替换语法,感化在已分派的工具上,该工具已有准确的巨细和准确的赋值,这包含创建虚函数表和挪用机关函数。
  译者注:placementnew就是在用户指定的内存地位上构建新的工具,这个构建历程不必要分外分派内存,只必要挪用工具的机关函数便可。placementnew实践上是把底本new做的两步事情分隔来:第一步本人分派内存,第二步伐用类的机关函数在本人已分派的内存上构建新的工具。placementnew的优点:1)在已分派好的内存长进行工具的构建,构建速率快。2)已分派好的内存能够重复使用,无效的制止内存碎片成绩。
  1. #include<iostream>usingnamespacestd;structTest{intdata;Test(){cout<<"Test::Test()"<<endl;}~Test(){cout<<"Test::~Test()"<<endl;}};intmain(){//MustallocateourownmemoryTest*ptr=(Test*)malloc(sizeof(Test));//Useplacementnewnew(ptr)Test;//Mustcallthedestructorourselvesptr->~Test();//Mustreleasethememoryourselvesfree(ptr);return0;}
复制代码
  当在功能关头的场所必要自界说分派器时可使用Placementnew。比方,一个slab分派器从单个的年夜内存块入手下手,利用placementnew在块里按次分派工具。这不但制止了内存碎片,也节俭了malloc引发的堆遍历的开支。
  在声明变量的同时举行分支

  C++包括一个语法缩写,能在声明变量的同时举行分支。看起来既像单个的变量声明也能够有if或while如许的分支前提。
  1. structEvent{virtual~Event(){}};structMouseEvent:Event{intx,y;};structKeyboardEvent:Event{intkey;};voidlog(Event*event){if(MouseEvent*mouse=dynamic_cast<MouseEvent*>(event))std::cout<<"MouseEvent"<<mouse->x<<""<<mouse->y<<std::endl;elseif(KeyboardEvent*keyboard=dynamic_cast<KeyboardEvent*>(event))std::cout<<"KeyboardEvent"<<keyboard->key<<std::endl;elsestd::cout<<"Event"<<std::endl;}
复制代码
  成员函数的援用润色符

  C++11同意成员函数在工具的值范例长进行重载,this指针会将该工具作为一个援用润色符。援用润色符会放在cv限制词(译者注:CV限制词有三种:const限制符、volatile限制符和const-volatile限制符)不异的地位并根据this工具是左值仍是右值影响重载剖析:
  1. #include<iostream>structFoo{voidfoo()&{std::cout<<"lvalue"<<std::endl;}voidfoo()&&{std::cout<<"rvalue"<<std::endl;}};intmain(){Foofoo;foo.foo();//Prints"lvalue"Foo().foo();//Prints"rvalue"return0;}
复制代码
  转向完全的模板元编程

  C++模板是为了完成编译时元编程,也就是该程序能天生别的的程序。计划模板体系的初志是举行复杂的范例交换,可是在C++尺度化过程当中俄然发明模板实践上功效非常壮大,足以实行恣意盘算,固然很愚笨很低效,但经由过程模板特化切实其实能够完成一些盘算:
  1. //Recursivetemplateforgeneralcasetemplate<intN>structfactorial{enum{value=N*factorial<N-1>::value};};//Templatespecializationforbasecasetemplatestructfactorial<0>{enum{value=1};};enum{result=factorial<5>::value};//5*4*3*2*1==120
复制代码
  C++模板能够被以为是一种功效型编程言语,由于它们利用递回而非迭代并且包括不成变形态。你可使用typedef创立一个恣意范例的变量,利用enum创立一个int型变量,数据布局内嵌在范例本身。
  1. //Compile-timelistofintegerstemplate<intD,typenameN>structnode{enum{data=D};typedefNnext;};structend{};//Compile-timesumfunctiontemplate<typenameL>structsum{enum{value=L::data+sum<typenameL::next>::value};};templatestructsum<end>{enum{value=0};};//Datastructuresareembeddedintypestypedefnode<1,node<2,node<3,end>>>list123;enum{total=sum<list123>::value};//1+2+3==6
复制代码
  固然这些例子没甚么用,但模板元编程切实其实能够做一些有效的事变,好比能够操纵范例列表。可是,利用C++模板的编程言语可用性极低,因而请审慎和大批利用。模板代码很难浏览,编译速率慢,并且因其冗杂和利诱的毛病信息而难以调试。
  指向成员的指针操纵符

  指向成员的指针操纵符可让你在一个类的任何实例上形貌指向某个成员的指针。有两种pointer-to-member操纵符,取值操纵符*和指针操纵符->:
  1. #include<iostream>usingnamespacestd;structTest{intnum;voidfunc(){}};//Noticetheextra"Test::"inthepointertypeintTest::*ptr_num=&Test::num;void(Test::*ptr_func)()=&Test::func;intmain(){Testt;Test*pt=newTest;//Callthestoredmemberfunction(t.*ptr_func)();(pt->*ptr_func)();//Setthevariableinthestoredmemberslott.*ptr_num=1;pt->*ptr_num=2;deletept;return0;}
复制代码
  该特性实践上非常有效,特别在写库的时分。比方,Boost::Python,一个用来将C++绑定到Python工具的库,就利用成员指针操纵符,在包装工具时很简单的指向成员。
  1. //加括号打消歧义std::stringfoo((std::string()));intbar((int(x)));0
复制代码
  记着利用成员函数指针与一般函数指针是分歧的。在成员函数指针和一般函数指针之间casting是有效的。比方,Microsoft编译器里的成员函数利用了一个称为thiscall的优化挪用商定,thiscall将this参数放到ecx存放器里,而一般函数的挪用商定倒是在栈上剖析一切的参数。
  并且,成员函数指针大概比一般指针年夜四倍摆布,编译器必要存储函数体的地点,到准确父地点(多个承继)的偏移,虚函数表(虚承继)中另外一个偏移的索引,乃至在工具本身外部的虚函数表的偏移也必要存储(为了前向声明范例)。
  1. //加括号打消歧义std::stringfoo((std::string()));intbar((int(x)));1
复制代码
  在DigitalMars编译器里一切的成员函数都是不异的巨细,这是源于如许一个伶俐的计划:天生“thunk”函数来使用右偏移而不是存储指针本身外部的偏移。
  静态实例办法

  C++中能够经由过程实例挪用静态办法也能够经由过程类间接挪用。这可使你不必要更新任何挪用点就能够将实例办法修正为静态办法。
  1. //加括号打消歧义std::stringfoo((std::string()));intbar((int(x)));2
复制代码
  重载++和&ndash;

  C++的计划中自界说操纵符的函数称号就是操纵符自己,这在年夜部分情形下都事情的很好。比方,一元操纵符的-和二元操纵符的-(取反和相减)能够经由过程参数个数来辨别。但这关于一元递增和递加操纵符却不见效,由于它们的特性仿佛完整不异。C++言语有一个很愚笨的技能来办理这个成绩:后缀++和&ndash;操纵符必需有一个空的int参数作为标志让编译器晓得要举行后缀操纵(是的,只要int范例无效)。
  1. //加括号打消歧义std::stringfoo((std::string()));intbar((int(x)));3
复制代码
  操纵符重载和反省按次

  重载,(逗号),||大概&&操纵符会引发凌乱,由于它冲破了一般的反省划定规矩。一般情形下,逗号操纵符在全部右边反省终了才入手下手反省右侧,||和&&操纵符有短路举动:仅在需要时才会往反省右侧。不管怎样,操纵符的重载版本仅仅是函数挪用且函数挪用以未指定的按次反省它们的参数。
  重载这些操纵符只是一种滥用C++语法的体例。作为一个实例,上面我给出一个Python情势的无括号版打印语句的C++完成:
  1. //加括号打消歧义std::stringfoo((std::string()));intbar((int(x)));4
复制代码
  函数作为模板参数

  尽人皆知,模板参数能够是特定的整数也能够是特定的函数。这使得编译器在实例化模板代码时内联挪用特定的函数以取得更高效的实行。上面的例子里,函数memoize的模板参数也是一个函数且只要新的参数值才经由过程函数挪用(旧的参数值能够经由过程cache取得):
  1. //加括号打消歧义std::stringfoo((std::string()));intbar((int(x)));5
复制代码
  模板的参数也是模板

  模板参数实践上本身的参数也能够是模板,这可让你在实例化一个模板时能够不必模板参数就可以够传送模板范例。看上面的代码:
  1. //加括号打消歧义std::stringfoo((std::string()));intbar((int(x)));6
复制代码
  CachedStore的cache存储的数据范例与store的范例不异。但是我们在实例化一个CachedStore必需反复写数据范例(下面的代码是int型),store自己要写,CachedStore也要写,关头是我们这其实不能包管二者的数据范例是分歧的。我们真的只想要断定数据范例一次便可,以是我们能够强迫其稳定,可是没有范例参数的列表会引发编译堕落:
  1. //加括号打消歧义std::stringfoo((std::string()));intbar((int(x)));7
复制代码
  模板的模板参数可让我们取得想要的语法。注重你必需利用class关头字作为模板参数(他们本身的参数也是模板)
  1. //加括号打消歧义std::stringfoo((std::string()));intbar((int(x)));8
复制代码
  try块作为函数

  函数的try块会在反省机关函数的初始化列表时捕捉抛出的非常。你不克不及在初始化列表的四周加上try-catch块,由于其只能呈现在函数体外。为懂得决这个成绩,C++同意try-catch块也可作为函数体:
  1. //加括号打消歧义std::stringfoo((std::string()));intbar((int(x)));9
复制代码
  奇异的是,这类语法不单单范围于机关函数,也可用于其他的一切函数界说。
  原文链接:EvanWallace翻译:伯乐在线-敏敏
写学习日记,这是学习历程的见证,同时我坚持认为是增强学习信念的法宝。以上是我学习Linux的心得体会,希望对大家的学习有所帮助,由于水平有限,本文难免有所欠缺,望请指正。
分手快乐 该用户已被删除
沙发
发表于 2015-1-18 07:47:34 | 只看该作者
此外,在实训中,我还认识到自己的粗心。在编程时,粗心的把一语言写错,导致结果运行不了。在以后的学习中,我要特别注意小节,要认真对待。
老尸 该用户已被删除
板凳
发表于 2015-1-25 14:46:31 | 只看该作者
最好的学习方式还是去理解书中给的那个Sales_item类的设计。从基类到派生类,从普通成员函数到虚函数,它们的一些构造,复制,析构函数存在着千丝成关系,学习的时候画画比较图,多分析。
飘灵儿 该用户已被删除
地板
发表于 2015-2-2 22:34:21 来自手机 | 只看该作者
这一部分,你开始可能觉得知识点太多太碎,没有关系,记住有哪几个容器,各自有什么特点就行,以后遇到了需求,回头来查,如果有数据结构的基础那就非常容易记忆理解了。
爱飞 该用户已被删除
5#
发表于 2015-2-8 17:05:58 | 只看该作者
关于C++中string和vector的使用,在C++的规范标准之后,正式提出了标准库类型string和vector。
只想知道 该用户已被删除
6#
 楼主| 发表于 2015-2-25 21:45:49 | 只看该作者
在编程序时,我也学会了敢于尝试,“不试不知道,试试就能行”这是我在实训中领悟的道理之一。
若天明 该用户已被删除
7#
发表于 2015-3-8 08:27:17 | 只看该作者
用的vector,而很少使用了数组。当然在我现在的能力范围内,还很难驾驭vector,毕竟数组当年也是我的最爱,相比于更加难缠的指针控制来说。
海妖 该用户已被删除
8#
发表于 2015-3-15 22:27:52 | 只看该作者
否极泰来。在你专注一个技术极度郁闷得时候不要放弃,可以暂时放弃,但是请马上回来,因为灵感在等你。黎明前确实是黑暗,但是到了黎明,下面就是很长一段得光明。
小妖女 该用户已被删除
9#
发表于 2015-3-22 17:19:13 | 只看该作者
实训的项目是高级语言程序设计。说实话,在这么多科目中,这是我学得最糟糕的一科。刚开始,我对这实训没什么信心,不知能否按时完成。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-12-23 07:50

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表