雕刻时光

just do it……nothing impossible
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

随笔分类 -  c++基础知识

摘要:引子:在算法运用迭代器的时候,很可能用到起相应型别(即迭代器所指之物的型别),但C++支持sizeof ,并无typeof。 可以利用function template的参数推导机制。1.函数参数的情况#includeusing namespace std;template void func_impl(I iter,T t){ T tmp;//这里解决了问题,T就是迭代器所指之物的类型 //…………}template void func(I iter){ func_impl(iter,*iter);}int main(){ int i; func(&i);}显... 阅读全文

posted @ 2013-12-10 14:13 huhuuu 阅读(449) 评论(0) 推荐(0) 编辑

摘要:引出:写个类A,声明类A指针指向NULL,调用类A的方法会有什么后果,编译通过吗,运行会通过吗?(在VS2008与VC++的情况下) 有错误欢迎批评指正!#include#includeusing namespace std;class base{ int a;public: void fun(){ printf("base fun\n"); }};int main(){ base *b=NULL; b->fun();}看到这个的时候,一定以为运行会报错吧。但是奇迹般的,编译器输出了:base fun#include#includeusing nam... 阅读全文

posted @ 2013-12-07 19:15 huhuuu 阅读(1274) 评论(3) 推荐(0) 编辑

摘要:我们往往在类中的函数体,重载操作中看到const T & 的影子,以前还是比较纳闷。 对于非内部数据类型的参数而言,象void Func(A a) 这样声明的函数注定效率比较底。因为函数体内将产生 A 类型的临时对象用于复制参数 a,而临时对象的构造、复制、析构过程都将消耗时间。 为了提高效率,可以将函数声明改为void Func(A &a),因为“引用传递”仅借用一下参数的别名而已,不需要产生临时对象。但是函数 void Func(A &a) 存在一个缺点:“引用传递”有可能改变参数 a,这是我们不期望的。解决这个问题很容易,加 const修饰即可,因此函数最终成为 阅读全文

posted @ 2013-12-05 22:45 huhuuu 阅读(540) 评论(0) 推荐(0) 编辑

摘要:#include#include#include#include#includeusing namespace std;class Base{private: int x; char *p;public: Base(void){ x=0; p=(char *)malloc(sizeof(10)); strcpy(p,"123456"); } void Set_x(int tx){ x=tx; } //函数名后面加const表示这个对象指针this所指之物是无法改变的 int Get_x()c... 阅读全文

posted @ 2013-12-05 22:30 huhuuu 阅读(6141) 评论(0) 推荐(0) 编辑

摘要:在编写派生类的赋值函数时,注意不要忘记对基类的数据成员重新赋值。#include#include#include#include#includeusing namespace std;class Base{private: int x,y;public: Base& operator =(const Base &other){ x=other.x; y=other.y; printf("Base operator\n"); return *this; } Base(){ x=0;y=0; ... 阅读全文

posted @ 2013-12-05 21:32 huhuuu 阅读(433) 评论(0) 推荐(0) 编辑

摘要:#include#include#include#include#includeusing namespace std;class mystring{public: mystring(const char *str=NULL); mystring(const mystring &other); ~mystring(void); mystring &operator=(const mystring &other); mystring &operator+=(const mystring &other); char *getString();private: 阅读全文

posted @ 2013-12-05 19:35 huhuuu 阅读(237) 评论(0) 推荐(0) 编辑

摘要:#includeusing namespace std;class Obj{public : Obj(){coutInit(); //~~~~~ a->Destroy(); free(a);}void new_test(){ Obj * a=new Obj; delete a;}int main(){ malloc_test(); new_test();}除了前者是函数,后者是标识符的区别外前者是在C语言中诞生的,用于内存分配但是不会执行构造函数与析构函数。(这里没有继承,要是有继承关系,用free就难以处理从派生类到基类的析构了,内存泄露在所... 阅读全文

posted @ 2013-12-05 14:08 huhuuu 阅读(441) 评论(0) 推荐(0) 编辑

摘要:前段时间一直想看malloc的原理,在搜了好几篇malloc源码后遂放弃,晦涩难懂。 后来室友买了本深入理解计算机系统的书,原来上面有讲malloc的原理,遂看了,先明白理论,在看代码就理解比较快了= = 1.问题的引入: 为什么要使用malloc,主要是因为在代码中,为了节约内存,很多数据都是动态生成的,所以会用malloc,对应于C++中的new,底层还是调用malloc. 2.碎片的问题: 会有内部碎片与外部碎片的问题,内部碎片难以消除(因为字对齐之类的问题),而外部碎片是可以消除的(如果不消除的话,外部的内存块越来越小,虽然数量多了,但是利用率会急剧下降!) 3.需... 阅读全文

posted @ 2013-12-03 22:34 huhuuu 阅读(13905) 评论(1) 推荐(3) 编辑

摘要:1. 编译器的优化在本次线程内, 当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以便保持一致。当变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致。当该寄存器在因别的线程等而改变了值,原变量的值不会改变,从而造成应用程序读取的值和实际的变量值不一致。2.volatile应该解释为“直接存取原始内存地址”比较合适,“易变的”这种解释简直有点误导人。加上volatile 实际上就直接从内存中读取,避免了被编译 阅读全文

posted @ 2013-12-02 19:16 huhuuu 阅读(347) 评论(0) 推荐(0) 编辑

摘要:实践出真理!#include#includeclass A{public:A(); virtual~A(); virtual void fun1(){ printf("A:fun1"); } virtual void fun2(){ printf("A:fun2"); }};A::A(){}A::~A(){ printf("Delete class A\n");}class B : public A{public:B(); ~B(); void fun1(){ ... 阅读全文

posted @ 2013-12-02 18:07 huhuuu 阅读(1160) 评论(0) 推荐(0) 编辑

摘要:1.构造函数能否声明为虚函数: 构造函数不能声明为虚函数,虚函数对应一个vptr,可是这个vptr其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vptr来调用,可是对象还没有实例化,也就是内存空间还没有,怎么找vptr呢?所以构造函数不能是虚函数。(而且现在VS的编译器一般也会报错)。2.析构函数能否声明为虚函数:析构函数可以声明为虚函数,而且有时是必须声明为虚函数,是因为删除指向派生类的基类指针的时候,如果析构函数不是虚函数,派生类的析构函数将不会被执行,直接后果的内存泄漏!!!3.能否在构造函数里面调用虚函数:编译不会报错,但是最好不要这样做!在调用构造这时候类 阅读全文

posted @ 2013-12-02 15:42 huhuuu 阅读(1062) 评论(0) 推荐(0) 编辑

摘要:#include#includeusing namespace std;class base1{public: base1(){ printf("start base1\n"); } ~base1(){ printf("end base1\n"); }private: int mx,my; int mi,mj;};class base2:public base1{public: base2(){ printf("start base2\n"); } ~base2(){ ... 阅读全文

posted @ 2013-12-02 09:42 huhuuu 阅读(321) 评论(0) 推荐(0) 编辑

摘要:析构函数的作用与构造函数正好相反,是在对象的生命期结束时,释放系统为对象所分配的空间,即要撤消一个对象。用对象指针来调用一个函数,有以下两种情况:如果是虚函数,会调用派生类中的版本。(在有派生类的情况下)如果是非虚函数,会调用指针所指类型的实现版本。析构函数也会遵循以上两种情况,因为析构函数也是函数嘛,不要把它看得太特殊。 当对象出了作用域或是我们删除对象指针,析构函数就会被调用。当派生类对象出了作用域,派生类的析构函数会先调用,然后再调用它父类的析构函数, 这样能保证分配给对象的内存得到正确释放。但是,如果我们删除一个指向派生类对象的基类指针,而基类析构函数又是非虚的话, 那么就会先调用基类 阅读全文

posted @ 2013-12-01 22:11 huhuuu 阅读(10687) 评论(0) 推荐(0) 编辑

摘要:C++的特性之一就是多态,多态的特性就是通过虚函数来实现的,而虚函数就是通过一个虚函数表来实现的。 (关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议。) #include using namespace std;class Base1 {public: virtual void f() { cout << "Bas 阅读全文

posted @ 2013-11-29 22:32 huhuuu 阅读(410) 评论(0) 推荐(0) 编辑

摘要:可能指针函数与函数指针的概念不是很清楚1.指针函数的概念其实跟普通函数的概率类似,就是一个函数的返回值是个指针类型!#include#includeusing namespace std;int *pointFun(){ int *p=(int *)malloc(sizeof(int)); *p=1; return p;}int main(){ int *ptemp=pointFun(); printf("%d\n",*ptemp);}2.函数指针还是比较有来头的观察以下函数#include#includeusing namespace std;void myfu... 阅读全文

posted @ 2013-11-29 21:55 huhuuu 阅读(1930) 评论(2) 推荐(0) 编辑

摘要:在现实地图应用中,有个比较常见的问题,比如,你到了一个地方,想查查附近1km内有什么饭店。 这时地图应用就可以马上查询出周围有什么饭店,如果让你设计,你会怎么设计。假设局限在中国的地图上,共有1000000(用N表示)家饭店,每个饭店就2个信息量(经度x与纬度y),你现在到了某个地方(三个信息量,经度x2与纬度x2,还有以你为中心圆的半径 R个单位),假设这些数据在内存中是有序的,并且在小范围内点与点的信息存在邻接表内。 方法一:枚举,这个通过你所在的坐标与N个饭店进行比较,在R范围内的就输出,反之不输出。时间复杂度O(N),当饭店数量很大的时候,搜索速度就会很慢。 方法二:考虑到数... 阅读全文

posted @ 2013-11-27 21:58 huhuuu 阅读(760) 评论(0) 推荐(0) 编辑

摘要:转自http://www.cnblogs.com/coder2012/p/3330311.htmlhttp://blog.sina.com.cn/s/blog_6776884e0100ohvr.html这篇在大体上比较清晰简单的描述了概念,比较通俗易懂B-tree B-tree,B是balance,一般用于数据库的索引。使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度。而B+tree是B-tree的一个变种,大名鼎鼎的MySQL就普遍使用B+tree实现其索引结构。 那数据库为什么使用这种结构? 一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索.. 阅读全文

posted @ 2013-11-26 10:24 huhuuu 阅读(2542) 评论(0) 推荐(0) 编辑

摘要:一个进程相当于你写了的一个程序正在内存中运行,而这个进程内至少有一个主线程,C++就是main(),还有辅助线程,当然一旦主线程结束了,辅助线程就都结束了,这样就可以比较清晰地理解,进程是资源分配的基本单位,而线程,是共用进程中的资源的,同时操作系统就给了进程一部分内存堆和cpu处理的时间。 下面的函数可以观察两个辅助线程的运行情况 下面的程序有两个辅助线程,没有临界资源#include #include#include#include#include#include#include#include #includeusing namespace std;DWORD WINAPI Fu... 阅读全文

posted @ 2013-11-25 22:32 huhuuu 阅读(410) 评论(0) 推荐(0) 编辑

摘要:之前写了一篇堆栈的,这里再补充下内存其他的区域1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 2、堆区(heap) — 一般由程序员分配释放 , 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。 3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域(BSS)。 - 程序结束后由系统释放 4、文字常量区 — 常量字符串就是放在这里的。 程序结束后由系统释放 阅读全文

posted @ 2013-11-24 16:38 huhuuu 阅读(11269) 评论(2) 推荐(3) 编辑

摘要:先观察一下的代码:#includeint main(){ const int i=1; int y; int *pi=(int*)&i; *pi=2; y=*pi; int tempi; tempi=i; printf("i=%d\n",i); printf("tempi=%d\n",tempi); printf("y=%d\n",y);}输出的是i=1tempi=1y=2观察内存在执行完*pi=2后i被神奇的修改了,但是tempi=i 后 tempi 依旧1这时观察汇编你惊奇地发现,在编译成汇编的时候,temp=i 压根就没 阅读全文

posted @ 2013-11-24 11:14 huhuuu 阅读(1802) 评论(2) 推荐(0) 编辑