随笔 - 576  文章 - 0  评论 - 62  阅读 - 219万

随笔分类 -  C++

上一页 1 2 3 4 5 6 7 下一页
引用计数
摘要:什么是引用计数?一个在堆上创建的对象,记录有多少个指针指向它。为什么要设计引用计数,他解决什么问题?1、new出一个临时对象,使用完了,需要delete。但是拥有权会转移(auto_ptr)或者扩散,因此很难确定delete时机。忘记delete导致资源泄漏,过早delete,导致还在使用的指针出现错误,重复delete导致未定义行为。2、许多对象拥有相同的值,存储多次是个很愚蠢的事,可以共享。如何实现:1、以String为例说明,String s1 = "Hello", String s2 = s1; 可以让s1,s2共享"Hello"。2、引用计数放 阅读全文
posted @ 2013-12-02 20:45 Andy Niu 阅读(1361) 评论(0) 推荐(0) 编辑
C++为什么不支持某些东西
摘要:1、学习C++的过程,经常发现C++不支持一些东西,思考下,为什么?2、C++不支持一些东西,有两个原因: a、可以做到,但是会导致一些不合理的结果,这些结果往往与程序员的期望不一致。 b、属于“臣妾做不到啊”3、对于第一种情况,比如: a、传引用,存在隐式类型转换,会建立一个临时对象。对引用的修改,不能体现在原对象身上,与程序员期望不一致,C++不支持。 b、p++++,编译器不支持。4、对于第二种情况,比如: C++不支持模版的分离式编译。5、C++能做什么,不能做什么,往往是由C++编译器决定的。C++做不到,往往是因为编译器做不到。比如: a、比如,不能这样创建对象Pers... 阅读全文
posted @ 2013-12-02 19:44 Andy Niu 阅读(273) 评论(0) 推荐(0) 编辑
C++ 不支持模版的分离式编译
摘要:1、C++不支持模版的分离式编译,为什么? C++是分别,单独编译,对于每个cpp文件,预编译为编译单元,这个编译单元是自包含文件,编译的时候,不需要其他的文件,编译好了,生成obj文件,然后连接成exe文件。在编译的时候,使用一个东西,如果这个东西就在当前位置,当然好了。如果不再当前位置,也没关系,只要说,我有这个东西就行,这个东西在其他地方。在连接的时候,会找到这个东西在什么地方。 考虑普通方法,通过上面的分析,是没有问题的。考虑模版方法: Fun.h声明一个方法模版,Fun.cpp包含Fun.h,并定义了方法模版,main.cpp包含Fun.h,然后使用方法。单独编译Fun.cpp... 阅读全文
posted @ 2013-12-02 19:34 Andy Niu 阅读(1355) 评论(0) 推荐(0) 编辑
方法名重整
摘要:1、为什么要进行方法名重整? C++支持过载,允许方法名相同,形参表不同。对于同名的方法,编译器根据形参表的不同,对方法名重整为另一个方法名,也就是建立一种映射。这就是为什么要进行方法名重整。同时编译器,进行了扩展,也就是说,没有过载的方法也进行了方法名重整。2、方法名重整带来的问题 C中没有过载的概念,也就是不允许出现同名的方法。因此,也就没有方法名重整。考虑下面的情况:在C++使用C语言库中的方法,int add(int a);C中提供了add方法的实现,C++中包含头文件,声明方法,然后使用。C代码生成的目标文件中,方法名没有重整,还是add,而C++代码方法名进行了重整,假设重整为.. 阅读全文
posted @ 2013-12-02 19:01 Andy Niu 阅读(259) 评论(0) 推荐(0) 编辑
前缀式与后缀式
摘要:1、考虑下面的场景:有一个Person类,内部有个age字段,对外提供前缀式和后缀式,把年龄加1。2、前缀式与后缀式都没有右操作数,也就是说没有形参,需要区分前缀式和后缀式,对于后缀式中增加一个形参。因为这个形参在方法内并不使用,可以省略形参名。3、前缀式和后缀式是操作符重载,本质上是方法,和GetName()一样。4、前缀式:1 Person& Person::operator ++()2 {3 this->age = this->age+1;4 return *this;5 }5、后缀式:1 const Person Person::operator ++(int)2 阅读全文
posted @ 2013-12-02 18:29 Andy Niu 阅读(3474) 评论(0) 推荐(0) 编辑
理解 __declspec(dllexport)和__declspec(dllimport)
摘要:1、解决的问题: 考虑下面的需求,使用一个方法,一个是提供者,一个是使用者,二者之间的接口是头文件。头文件中声明了方法,在提供者那里方法应该被声明为__declspec(dllexport),在使用者那里,方法应该被声明为__declspec(dllimport)。二者使用同一个头文件,作为接口,怎么办呢?2、解决办法: 使用条件编译:定义一个变量,针对提供者和使用者,设置不同的值。 1 #ifndef DLL_H_ 2 #define DLL_H_ 3 4 #ifdef DLLProvider 5 #define DLL_EXPORT_IMPORT __declspec(dllexpo... 阅读全文
posted @ 2013-11-28 20:15 Andy Niu 阅读(32142) 评论(2) 推荐(1) 编辑
方法的确定
摘要:1、方法有三个部分:方法的拥有者,方法名,方法形参表。2、对象有表面类型和真实类型,编译器编译的时候,仅仅知道对象的表面类型,而不知道对象的真实类型。3、调用方法的时候,有很多同名方法,到底调用那个方法呢?4、依据是: a、如果是virtual方法,根据方法拥有者的真实类型,决定调用哪个方法。 b、根据形参表的表面类型,决定调用哪个方法。 阅读全文
posted @ 2013-11-28 19:44 Andy Niu 阅读(332) 评论(0) 推荐(0) 编辑
vector 与map的下标操作
摘要:1、vector的下标操作不会添加元素,只能针对已经存在的元素操作。2、map的下标操作具有副作用,key不存在,会在map中添加一个具有该key的新元素,新元素的value使用默认构造方法。3、为什么要这样设计? vector是基于连续内存的容器,在尾部操作效率高,使用push_back添加元素,使用下标必须保证下表存在元素。 map是基于节点的容器,元素有序。使用下标操作,第一步是查找key是否存在,map的内部实现是二叉树(AVL树或者红黑树),采用二分查找。不管是否存在key,查找key 的时候,也已经确定了key的位置。因此,如果不存在key,干脆添加一个,反正已经知道添加位置,.. 阅读全文
posted @ 2013-11-26 18:57 Andy Niu 阅读(3841) 评论(0) 推荐(0) 编辑
静态成员与实例成员
摘要:1、类的成员分为静态成员和实例成员。为什么设计出静态成员和实例成员? 静态成员对类以及类的所有实例有意义,实例成员对每个实例有意义。考虑,Person类,有个age字段和maxAge字段。每个Person实例都有自己的age,但所有的Person实例都有相同的maxAge(最大年龄极限),因此,maxAge只需要一份就好了,大家共享。有两个好处:节约内存和保持一致。2、成员分为字段和方法,首先考虑字段: 静态字段:只有一块内存。 实例字段:每个实例都有专属于自己的一块内存。3、对于方法: 无论静态方法和实例方法,只有一块内存。那么问题来了,在成员方法中会使用实例的字段,怎么区分是哪个实... 阅读全文
posted @ 2013-11-25 20:08 Andy Niu 阅读(2428) 评论(0) 推荐(0) 编辑
const 成员方法
摘要:1、使用场景 代码提供者告诉客户(代码使用者),这个方法不会修改对象的内容,请客户放心使用。2、代码提供者,尝试在const成员方法中修改对象内容,编译报错。在成员方法中,this是const 指针,不允许修改this指向其他内容。const 成员方法,限制了this为指向const对象的const指针。3、const对象只能调用const成员方法,因为non-const成员方法可能会修改对象内容,这与const对象矛盾。4、non-const对象可调用const成员方法,也可以调用non-const成员方法。5、为什么可以做到上面的约束? 如果B是A的别名(包括引用,指针),则B不能放大.. 阅读全文
posted @ 2013-11-25 19:33 Andy Niu 阅读(227) 评论(0) 推荐(0) 编辑
C++ 预编译头文件
摘要:1、解决什么问题? C++ 编译器是单独,分别编译的,每个cpp文件,进行预编译(也就是对#include,define 等进行文本替换),生成编译单元。编译单元是一个自包含文件,C++编译器对编译单元进行编译。考虑,头文件A.h被多个cpp文件(比如A1.cpp,A2.cpp)包含,每个cpp文件都要进行单独编译,其中的A.h部分就会被多次重复第编译,影响效率。2、怎么解决? 把A.h以及类似A.h这样的头文件,包含到stdafx.h中(当然也可以是其他文件),在stdafx.cpp中包含stdafx.h,设置stdafx.cpp文件的属性,预编译头设置为 创建。对于原先包含A.h的cp.. 阅读全文
posted @ 2013-11-22 16:42 Andy Niu 阅读(12453) 评论(0) 推荐(1) 编辑
C++ 对象没有显式初始化
摘要:C++ 对象没有显式初始化,结果是什么?首先考虑非静态对象1、方法内的局部对象: a、类类型:调用default构造方法 b、基本类型:值不确定2、类中的数据成员: a、类类型:调用default构造方法 b、基本类型:值不确定注意:Person p; 调用default构造方法,不能使用 Person p(),对于Person p(),编译器会认为声明一个方法。当然也可以使用 Person p = Person();考虑静态对象:1、方法内的局部对象: a、类类型:调用default构造方法,注意:类对象中的基本类型对象,即使没有显式初始化,也会初始化为0 b、基本类型:02、类... 阅读全文
posted @ 2013-11-22 14:13 Andy Niu 阅读(779) 评论(0) 推荐(1) 编辑
C++ 析构方法
摘要:1、什么是析构方法? 析构方法与构造方法互补。2、为什么设计析构方法? 构造方法创建一个对象,对象内部往往还会申请一些资源。设计析构方法的目的是 释放资源,同时销毁自身。3、析构方法可以认为分为两个:显式析构方法和合成析构方法。 显式析构方法用于:释放对象申请的资源,也就是指针指向的对象。 合成析构方法用于:销毁自身,对于对象的每一个数据成员(不包括继承的数据成员),进行析构。继承的数据成员通过父类的合成析构方法进行析构。4、即使编写了显示析构方法,合成析构方法仍然会运行。首先使用显式析构方法释放资源,再调用合成析构方法销毁自身。5、如果对象没有申请资源,显式析构方法不需要做任何事,也... 阅读全文
posted @ 2013-11-21 17:46 Andy Niu 阅读(2789) 评论(0) 推荐(0) 编辑
C++ 异常
摘要:1、什么是异常? 异常就是程序出现了错误。2、为什么设计异常? 库(任何代码)的提供者检测出运行时出现的错误,但是不知道怎么处理。而库的使用者(客户)知道怎么处理这些错误,但是不知道何时发生(如果很明确知道何时发生,就可以在客户端处理了,不再留给库)。简单说,设计异常的目的就是:问题检测与问题处理相分离。3、使用错误码也可以表示错误,但是不好。为什么? a、缺乏语义; b、可以被忽略,异常不能被忽略,抛出异常不处理,会导致程序终止; c、缺乏调用堆栈的上下文; d、错误码必须一级一级传回去,异常可以跳级。4、catch是最先匹配,而不是最优匹配。因此,范围小的异常(具体的异常)放在... 阅读全文
posted @ 2013-11-19 10:11 Andy Niu 阅读(394) 评论(0) 推荐(0) 编辑
隐式类型转换 与 隐式类型转换操作符
摘要:1、考虑下面的情况:有个Person类,内部有个age字段。正常情况下,定义和赋值为:Person p = Person(8);p = Person(9);但是有个家伙很懒,他想这么写:Person p = 8;p =9;这样写也是可以的,因为编译器知道你的意图,运行的时候会进行一次隐式类型转换,中间适配一个临时对象。这就是隐式类型转换,但这样写不好,因为语义不通。要避免这种情况,使用explicit,这样编译器就会曝出错误。2、现在在考虑下面的需求:判断p的年龄是否大于5,正常的写法是:if(p.GetAge()>5){....}但是,上面的家伙还是很懒,想直接这样写:if(p> 阅读全文
posted @ 2013-11-14 14:10 Andy Niu 阅读(845) 评论(0) 推荐(0) 编辑
C++ 临时对象
摘要:1、什么是临时对象? swap方法中,常常定义一个temp对象,这个temp对象不是临时对象,而是局部对象。这里所说的临时对象是不可见的,在原代码中是看不到的。2、为什么会产生临时对象? a、客户期望的数据与你提供的数据不一致,需要隐式类型转换,中间需要适配一下,建立一个临时对象。 b、方法返回值,他是没有名字的,起到一个传递作用,方法内部的局部对象-->方法返回值-->主调方法中的接受对象。 c、异常处理,分为两个过程:抛出异常,捕获异常。抛出异常相当于return 方法内的局部对象,外部要有一个匿名的临时对象接收。catch语句类似于调用方法,将临时对象传给catch语句。3、 阅读全文
posted @ 2013-11-13 17:38 Andy Niu 阅读(2698) 评论(0) 推荐(0) 编辑
【转】C++ static关键字
摘要:原文:http://blog.csdn.net/hackbuteer1/article/details/7487694C++的static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static。前者应用于普通变量和函数,不涉及类;后者主要说明static在类中的作用。一、面向过程设计中的static1、静态全局变量在全局变量前,加上关键字static,该变量就被定义成为一个静态全局变量。我们先举一个静态全局变量的例子,如下:[cpp]view plaincopy#includeusingnamespacestd;staticintn;//定义静态全局变量voidfn() 阅读全文
posted @ 2013-11-12 15:52 Andy Niu 阅读(298) 评论(0) 推荐(0) 编辑
【转】C++ 异常
摘要:一、什么是异常处理 一句话:异常处理就是处理程序中的错误。二、为什么需要异常处理,以及异常处理的基本思想 C++之父Bjarne Stroustrup在《The C++ Programming Language》中讲到:一个库的作者可以检测出发生了运行时错误,但一般不知道怎样去处理它们(因为和用户具体的应用有关);另一方面,库的用户知道怎样处理这些错误,但却无法检查它们何时发生(如果能检测,就可以再用户的代码里处理了,不用留给库去发现)。 Bjarne Stroustrup说:提供异常的基本目的就是为了处理上面的问题。基本思想是:让一个函数在发现了自己无法处理的错误时抛出(throw)一个异常 阅读全文
posted @ 2013-11-12 10:06 Andy Niu 阅读(16725) 评论(1) 推荐(2) 编辑
C++ 转型
摘要:1、const_static的使用场景:接收一个const对象,但是想改变对象内容,使用const_static去除对象的常量性,然后可以修改对象。2、dynamic_static的使用场景:从子类向父类转化符合里氏代换,总是安全的。因此dynamic_static的使用场景主要是父类转化为子类,首先转化的结果必须是指针或者引用(指针转化失败返回Null,引用转化错误抛出异常),其次,要转化的对象必须是多态类型,所谓多态类型,也就是类型必须公有继承其他类,或者拥有虚函数(继承或者自定义)。3、reinterpret_cast的使用场景:有一个方法指针FunPtr,(void)(void),有一 阅读全文
posted @ 2013-11-11 20:00 Andy Niu 阅读(421) 评论(0) 推荐(0) 编辑
理解模版
摘要:1、解决的问题:考虑下面的需求,现在有一个方法Fun,形参是实体A,在方法内调用A的启动方法,A.Start(),实体A可能是电脑,也可能使汽车,也可能使空调,对于每一类实体都要写一个内容相同的方法,这些方法构成过载。有没有更好的办法呢? 模版就是问了解决这个问题,通过使用一个占位符,再调用方法的时候,让编译器自动生成一个方法。2、模版是自动化的过载,是延迟的过载。如何理解? 首先,在调用方法的时候,编译器根据类型实参,自动生成一个过载方法。其次,一般的过载方法是在调用之前,就要写好,而模版是在调用的时候,才自动生成对应的方法。3、模版是编译时多态。对于上面提到的问题,还有一个解决办法,那.. 阅读全文
posted @ 2013-11-11 19:32 Andy Niu 阅读(257) 评论(0) 推荐(0) 编辑

上一页 1 2 3 4 5 6 7 下一页
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示