随笔分类 - C/C++编程
摘要:在使用C/C++进行编程的过程中,经常会遇到输入输出的问题。 对于C语言中, 1. 格式化输入输出。 在C语言中,最常用的格式化输入输出是scanf和printf函数。 和这两个函数对应的更安全的函数是fscanf和fprintf:指定文件指针 对于字符串的处理还有sscanf和sprintf:指定字符串 声明如下: int printf(const char *format, ...); int fprintf(FILE *stream, const char *format, ...); int sprintf(char *str, const char *format, ...);...
阅读全文
摘要:getline函数是一个比较常见的函数。根据它的名字我们就可以知道这个函数是来完成读入一行数据的。现在对getline函数进行一个总结。在标准C语言中,getline函数是不存在的。下面是一个简单的实现方式:intgetline_(chars[],intlim){intc,i;i=0;while((c=getchar())!=EOF&&c!='\n'&&i0)printf("%s\n",s);return0;}但是这个实现是有问题的,就是遇到空行的时候也会停止的。为了解决这个问题,我们需要重新考虑while循环的判断条件。在上
阅读全文
摘要:这儿所讨论的是x86机器下的内存分配。其他机器下的情况可能不一样。首先,下面是一段测试程序:#includeusingnamespacestd;intmain(){inta[]={1,2,3,4,5,0,-5,-4,-3,-2,-1};char*s="helloworld";char*s2="I'maboy";char*s3="helloworld";floatf=1.0f;doubled=1.0;printf("a:%0#x\n",a);printf("s:%0#x\n",s);pri
阅读全文
摘要:之前有文章介绍过临时对象和返回值优化RVO方面的问题。见此处。在C++中,返回对象这一点经常被诟病,因为这个地方的效率比较低,需要进行很多的操作,生成一些临时对象,如果对象比较大的会就会比较耗时。但是在编译器实现的时候,经常是对返回对象的情况进行优化,也就是进行返回值优化 。在g++中,这个是默认已经进行了优化。以前我希望看看到底C++怎么操作的,但是无法看到,就是因为G++进行了默认的返回值优化RVO。今天在晚上发现可以有一中方法来禁止这个RVO,可以参考这儿。具体来说就是在编译的时候,加上-fno-elide-constructors这个选项,即:g++ -o rvo_test rvo_t
阅读全文
摘要:1. 面向对象:封装(数据抽象)是基础,继承是手段,多态是目的;泛型编程:参数化类型(概念抽象)是基础,模板是手段,通用是目的2. 面向对象是运行时问题空间的多态,泛型编程是编译时算法空间的多态3. OO以Type为中心,GP以Concept为中心,而Concept完全独立于Type;OO的type是显式定义的,type之间的关系也是显式定义的,是语言支持的 ;GP的Concept是由算法隐式定义的,Concept之间的关系,是无法用目前的C++语法直接表达的;Concept的Model完全可以是毫无关系的Type,refinement独立于inheritence,original conc.
阅读全文
摘要:本篇内容来源于互联网 前言:复杂类型说明要了解指针,多多少少会出现一些比较复杂的类型,所以我先介绍一下如何完全理解一个复杂类型,要理解复杂类型其实很简单,一个类型里会出现很多运算符,他们也像普通的表达式一样,有优先级,其优先级和运算优先级一样,所以我总结了一下其原则:从变量名处起,根据运算符优先级结合,一步一步分析. 下面让我们先从简单的类型开始慢慢分析吧:intp;//这是一个普通的整型变量int*p;//首先从P处开始,先与*结合,所以说明P是一个指针,然后再与int结合,说明指针所指向的内容的类型为int型.所以P是一个返回整型数据的指针intp[3];//首先从P处开始,先与[]结合.
阅读全文
摘要:参考:http://blog.csdn.net/haoel/article/details/3081328,http://blog.csdn.net/haoel/article/details/3081385前言 07年12月,我写了一篇《C++虚函数表解析》 的文章,引起了大家的兴趣。有很多朋友对我的文章留了言,有鼓励我的,有批评我的,还有很多问问题的。我在这里一并对大家的留言表示感谢。这也是我为什么 再写一篇续言的原因。因为,在上一篇文章中,我用了的示例都是非常简单的,主要是为了说明一些机理上的问题,也是为了图一些表达上方便和简单。不想,这篇 文章成为了打开C++对象模型内存布局的一个引子
阅读全文
摘要:参考:http://www.cnblogs.com/itech/archive/2009/02/27/1399996.html一 虚继承1) 代码:#includeusingnamespacestd;classB{public:inti;virtualvoidvB(){cout(pB);pGD->i=10;pGD->x=20;pGD->y=30;pGD->a=40;PrintMemberAndVT(pGD);deletepGD;}6)验证代码结果:7)总结:虚继承,使公共的基类在子类中只有一份,我们看到虚继承在多重继承的基础上多了vbtable来存储到公共基类的偏移。二
阅读全文
摘要:之前有对虚函数机制的讲解,见这先讨论是多级继承的虚函数表。首先是没有函数覆盖的情况,继承方式如下图所示:对于实例DDerive dd;其所对应的虚函数列表是:测试代码如下:View Code classBase{public:typedefvoid(Base::*Fun)();virtualvoidf(){Funq=&Base::f;cout<<"Base::f->"<<(int)*(void**)&q<<endl;}virtualvoidg(){Funq=&Base::g;cout<<"
阅读全文
摘要:C++中的虚函数机制 虚函数的定义:虚函数必须是类的非静态成员函数(且非构造函数),其访问权限是 public(可以定义为 private or proteceted, 但是对于多态来说,没有意义)。在基类的类定义中定义虚函数的一般形式:virtual 函数返回值类型 虚函数名(形参表){ 函数体 }虚函数的作用是实现动态联编,也就是在程序的运行阶段动态地选择合适的成员函数,在定义了虚函数后,可以在基类的派生类中对虚函数重新定义(形式也是:virtual 函数返回值类型 虚函数名(形参表){ 函数体 }),在派生类中重新定义的函数应与虚函数具有相同的形参个数和形参类型。以实现统一的接口,不同定
阅读全文
摘要:内存对齐常量折叠 堆栈解退(stack unwinding) 模板特化模板偏特化 模板实例化 函数对象 单一定义规则(One-Definition Rule,ODR) 自引用 对象切片(object slicing)/切割:当把一个派生类对象赋给一个基类对象时,会发生对象切割。(另外用基类对象强制转换派生类对象也会),多态的实现是通过指针和引用;而对象的转换只会造成对象切割,不能实现多态。 所有权语义(owership semantics) 破坏性复制语义(distructive copy semantics) 菱形继承 向下强制:基类到派生类的转换 向上强制:派生类到基类的转换 交叉强制:从
阅读全文
摘要:常量 起初读者可能认为合乎逻辑的选择是把一个const放在类里,但这不会产生预期的结果。在一个类里,const 恢复它在C中的一部分意思。 它在每个类对象里分配存储并代表一个值,这个值一旦被初始化以后就不能改变。在一个类里使用const的意思是“在这个对象声明期内,这个是一个常量”。 然而,对这个常量来讲,每个不同的对象可以含一个不同的值。 把一个内部数据类型封装在一个类里以保证用构造函数初始化,是很用的。例如 class interger{int i;public:interger(int ...
阅读全文
摘要:1. 初始化一个引用变量必须在定义的时候。 而所有的运算符操作都被视为赋值而不是初始化,所以引用参数的初始化必须在初始化列表中进行。 class Test{ public: Test(int val) : ref_(val){} ~Test() {} private: int & ...
阅读全文
摘要:1、什么是static? static是C++中很常用的修饰符,它被用来控制变量的存储方式和可见性。 2、为什么要引入static? 函数内部定义的变量,在程序执行到它的定义处时,编译器为它在栈上分配空间,大家知道,函数在栈上分配的空间在此函数执行结束时会释放掉,这样就产生了一个问题: 如果想将函数中此变量的值保存至下一次调用时,如何实现? 最容易想到的方法是定义一个全局的变量,但定义为一个全局变量有许多缺点,最明显的缺点是破坏了此变量的访问范围(使得在此函数中定义的变量,不仅仅受此函数控制)。 3、什么时候用static? 需要 一个...
阅读全文
摘要:这是C++中所支持的两种初始化方式。复制初始化使用=符号,而直接初始化将初始化式放在圆括号中。(1)对于一般的内建类型,这两种初始化基本上没有区别。int a(5);//直接初始化int a=5;//复制初始化int a=int (5);//直接初始化(2)当用于类类型对象时,初始化的复制形式和直接形式有所不同:直接初始化直接调用与实参匹配的构造函数,复制初始化总是调用复制构造函数。复制初始化首先使用指定构造函数创建一个临时对象,然后使用复制构造函数将那个临时对象复制到正在创建的对象。string null_book = "9-999-99999-9 ";//copy-in
阅读全文
摘要:栈增长和大端/小端问题是和CPU相关的两个问题。在内存管理中,与栈对应是堆。对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方式是向下的,是向着内存地址减小的方向增长。在内存中,“堆”和“栈”共用全部的自由空间,只不过各自的起始地址和增长方向不同,它们之间并没有一个固定的界限,如果在运行时,“堆”和 “栈”增长到发生了相互覆盖时,称为“栈堆冲突”,系统肯定垮台。在常见的x86中内存中栈的增长方向就是从高地址向低地址增长。我们可以通过一些代码来判断栈的增长方向:#include<stdio.h>staticintstack_dir;staticvoid
阅读全文
摘要:今天在网上看到这个问题,自以为的输出是3.0,但是实际去跑一下,可以发现结果是0.0000这一句虽然不长,但是其中蕴涵的知识点是很多的。第一,10/3的结果是什么?这个很显然结果应该是3第二,printf语句格式化输出的使用%f就是要输出浮点数,但是我们也发现给的参数其实是个整型数。所以也就出现了上面的结果。第三,printf的原理是什么?这儿就牵扯到C中的不定参数的使用方法。具体可见这儿 简单来说就是,printf从栈中取参数的时候是根据格式化语句中要求进行取数的。这儿是%f,而浮点数是4个字节(32位操作系统),所以,要从栈中取4个字节,并且是按“浮点数的方式”。正好,参数3是个整型数,.
阅读全文
摘要:为栈实现高效的max操作 题目: 请设计一个栈,除了提供push(压栈),pop(出栈),peak(取栈顶元素)操作以外,还能提供max(取栈中最大值)的功能,并使得时间复杂度最小。注:请仔细思考后再看下面的答案1. 方案一(不可行)设计一个成员max,等于栈中最大的元素,在每次push操作后,新压入的元素与max比较,然后将max赋值为它们中的大的元素值。这样,max函数则返回max。问题:如果栈中等于max的元素pop出去后,该max就不是栈中的最大值了。2. 方案二(可行,效率太低)在【方案一】的基础上改进,每当栈中等于max的元素pop出去后,则把剩余元素依次pop到临时数组,找出最大
阅读全文
摘要:交换两个整型数是C/C++中最常见的操作。实现这个操作的方法很多。最基本的方法就是使用一个临时变量,具体的代码如下:inta,b;inttmp;tmp=a;a=b;b=tmp;如果以函数的形式写出来的话就是:voidswap(int*a,int*b){inttmp;tmp=*a;*a=*b;*b=tmp;}在C++中,可以使用引用来实现的比较优雅:voidswap(int&a,int&b){inttmp;tmp=a;a=b;b=tmp;}另外,还经常出现的一种情况是不使用临时变量来交换两个整型数,一般常见的方法有两种:加法和异或运算,具体如下表所示: ...
阅读全文