1.高质量软件开发之道;

高质量软件的属性:

高正确性:符合用户预期的实现了需求;

高健壮性:在各种场景下都可以正常运行,以及,出现异常之后可以自动恢复;

高可靠性:在有限时间内软件出现故障和错误的频率低;

高性能(效率):用较少的硬件资源实现更快的软件运行速度;

高易用性:与用户交互友好,使用简便;

高清晰性(可读性):可读性好,便于他人理解;

高安全性:他人通过该软件使用户遭受损失或伤害的可能性低;

高可扩展性:便于后续增加其他功能;

高兼容性:可以与其他软件交互信息;

高可移植性:软件可方便的运行于其他软硬件环境的;

个人思考:

对于以上属性重要程度的排序:

1.正确性;好的软件首先要正确,能符合用户预期的实现需求(即使是这点就不容易,有时客户都无法准确描述自己真正想要的是什么,需要你帮助他挖掘出来,需求的澄清与确认必不可少);

2.清晰性;没错,第二点就是可读性,我一直认为,代码实际上首先是写给人看的,然后才是给机器运行的;可读性好的代码可以为项目后续的进展节省大量的沟通成本,并且让风险可控,提高可维护性,可扩展性;

3.健壮性;可靠性;稳定的程序让人放心;

4.易用性;方便使用的程序让人愉快;

x.安全性,可扩展性,兼容性,可移植性;这几点得看具体的软件应用领域,在某些特定情况下,它们会很重要,有些情况下,它们又没那么重要;

从以上可以看出,写出好程序的最基础,最必须的条件是什么?理解需求,深入的,正确的理解了需求,才可以设计出合适的软件方案,才能对程序的各方面做出取舍。

高质量软件开发的基本方法:

1.建立软件过程规范;

2.复用

多复用别人重复使用的代码,这样的代码经过检验,同时也要多积累,形成属于自己的代码库

3.分而治之

合理的分解原始问题,模块化的设计程序解决被分解出的小问题;

个人思考:

原始问题被分解的合理程度,就是,对需求的理解程度和软件设计能力和经验的体现

4.优化与折中

优化是提高,不是可有可无的工作,是必须做的事情;

折中是协调各个软件质量属性,达到软件整体质量的最优;

5.技术评审

技术评审的目的是尽早的发现工作成果中的缺陷,并帮助开发人员及时消除缺陷,从而有效的提高软件质量;

6.测试

测试工作与开发工作同等重要;

测试的目的是尽可能多的发现缺陷;

测试能提高软件质量,但提高质量不能依赖测试;

测试的主要问题在于如何可以有效的进行测试,以及何时可以结束测试;

个人思考:

测试方案同样应当基于用户需求来设计,而不是基于开发人员的自测方案来设计

7.质量保证

质量保证的基本方法是通过有计划的检查“工作过程与成果”是否符合既定的规范。

8.改错

改错时,不要急于修改,要注意自己修改代码的波及范围;

回归测试方案的建立很有必要;

要注意反思与积累

2.编程语言发展简史;

掌握一门编程语言,不仅要求懂得语法,还要能熟练使用该语言的集成开发环境和相应的库函数。

3.程序的基本概念;

4.C++/C程序设计入门;

如果在某个声明中制定了某个标识符的连接规范为extern “C”,那么也要为其对应的定义指定extern “C”连接规范,如下所示:

#ifdef __cplusplus

extern "C" {

#endif

int __cdecl memcmp(const void *, const void *, size_t); //声明

#ifdef __cplusplus

}

#endif

#ifdef __cplusplus

extern "C" {

#endif

int _cdecl memcmp(const void * p, const void * a, size_t len)

{

…… //功能实现

}

#ifdef __cplusplus

}

#endif

(__cdecl 是C Declaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数不会要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误)

C语言环境中NULL值一般为void *类型,而C++环境中,由于允许从0到任何指针类型的隐式转型,因此NULL为整数0.即:

#ifdef __cplusplus

#define NULL 0

#else

#define NULL ((void *)0)

#endif

类型转换并不是改变原来的类型和值,而是生成了新的临时变量,其类型为目标类型。

由于派生类和基类之间的is-a关系,可以直接将派生类对象转换为基类对象,这虽然会发生内存截断,但无论从内存访问还是从转换结果来说都是安全的。这得益于C++的一个保证:派生类对象必须保证其基类子对象的完整性,即其中的基类子对象的内存映像必须和真正的基类对象的内存映像一致。

标准C语言允许任何非void类型指针和void类型指针之间进行直接的相互转换。但是在C++中,可以把任何类型的指针直接指派给void类型指针,因为void*是一种通用指针,但是不能反过来将void类型指针直接指派给任何非void类型指针,除非进行强制类型转换。

谨慎的进行数据类型转换,包括隐式类型转换和强制类型转换。

c/c++的标识符可以任意长,但是标准C语言中,编译器只取前31个字符作为有效的标识符,C++则取前255个字符。

比较两个浮点数,应该用如下方式:

假设有两个浮点变量x,y,精度定义为Z = le-6

if(abs(x - y)

if(abs(x - y) > Z) //x不等于y

for结构等价于下面的while结构:

while(循环控制条件表达式)

{

if(循环控制变量不等于其初始值)

修改循环控制变量;

语句序列;

}

在C++/C中应当以先行后列的方式遍历多维数组;

如果循环体内存在逻辑判断,并且循环次数很大,应该将逻辑判断移到循环外

循环次数较少时,则建议采用左边的方式,程序更简洁。

5.C++/C常量;

字面常量:各种进制的数字、字符(‘’括住的单个字符)或字符串(”“括住的一系列字符串)等;

字面常量智能引用,不能修改,所以语言实现一般把它保存在程序的符号表里面而不是一般的数据区中。符号表是“只读“的,这是一种访问保护机制,而不是存储在只读存储器(ROM)中。

符号常量:用#define定义的宏常量和用const定义的常量。由于宏常量在预编译阶段就被替换了,所以本质上是字面常量。

在C++程序中尽量使用const来定义符号常量,而不是#define;

在类中建立常量,用类中的枚举常量来实现;也可以用static const的方式来定义。

在C程序中,const符号常量的默认连接类型是外连接,就像全局变量一样;而在C++中,其默认连接类型是内连接,就像class的定义一样。在头文件中定义的const常量,会在每个编译单元(源文件)中都有一份拷贝,比较浪费空间,应当在头文件中声明,在源文件中定义;

6.C++/C函数设计基础;

如果函数没有参数,那么使用void而不要空着,因为标准C把空的参数列表解释为可以接受任何类型和个数的参数;而标准C++则把空的参数列表解释为不可以接受任何参数。

C语言中,函数的参数和返回值的传递方式有两种:值传递和地址传递;C++中增加了引用传递;

如果函数返回值是一个对象,要考虑return语句的效率:

return String(s1 + s2);

//这是创建一个临时对象并返回它,编译器会在函数栈外的存储区域直接创建该对象;

String result(s1 +s2);

return result;

//这里编译器会做三件事,创建result函数,并运行其构造函数,然后调用拷贝构造函数,把result拷贝到保存返回值的外部存储单元,然后result会在函数结束时被销毁(调用析构函数)。

C语言中为变量、常量和函数等定义了4中存储类型,即:extern、auto、static、register。

断言的语义如下:如果表达式的值为0,则输出错误消息并终止程序的执行;如果表达式为真,则不进行任何操作。

尽量使用const,常量,某些变量,某些函数的入参与返回值。

7.C++/C指针、数组和字符串;

虽然类型名和“*”组合是一种指针类型,但是编译器解释的时候,“*”是和其后的变量名结合的,如:

int * a, b, c;

编译器会理解为:只有a是int类型的指针,而b.c是int类型的变量。

数组在C/C++中就是地址传递,但是struct或class默认是值传递

动态创建字符数组:char * p = new char[100];

删除动态字符数组:delete []p;

strcpy和strcat会把源串的结束符一并拷贝到目标串中;strncpy和strncat则不会;

类的成员函数指针的声明和赋值:

class CTest

{

public:

void f(void){cout virtual void h(void){cout static void g(void){cout

private:

}

void main(void)

{

typedef void (*GFPtr)(void);

GFPtr fp = CTest::g;

fp();

typedef void (CTest::*MemFuncPtr)(void);

MemFuncPtr mfp_1 = &CTest::f;

MemFuncPtr mfp_2 = &CTest::h;

CTest theObj;

(theObj * mfp_1)();

(theObj * mfp_2)();

CTest * pTest = &theObj;

(pTest-> * mfp_1)();

(pTest-> * mfp_2)();

}

输出结果:

CTest::g()

CTest::f()

CTest::h()

CTest::f()

CTest::h()

类的静态成员函数不依赖于类的对象而存在,也不依赖于类的对象而调用,因此它和普通的全局函数没什么两样,只是其作用域变成了类作用域。普通成员函数和虚拟成员函数虽然也不依赖于类的对象而存在,但是其调用必须绑定到具体的对象。为了与静态成员函数区别,取其他两种成员函数的地址需要使用“&”运算符。任何成员函数的代码体都是独立于类的对象而存在的,只是非静态成员函数在调用的时候需要与具体的对象建立绑定关系(即this指针)。C/C++编译器最终会把所有的成员函数经过Name-Mangling的处理后转换成全局函数,并增加一个入参this作为第一个参数,供所属类的所有对象共享。另外由于纯虚函数没有实现体,且虚函数都是通过vptr和vtable来间接调用的,因此取虚函数的地址将得到该虚函数实现体在vtable中的索引号。要想得到虚函数实现体的真实地址,还需要首先从对象入手,找到vptr的位置,进而找到vtable的所在,然后根据函数指针的大小和虚函数的索引,取出虚函数的真实地址。

引用与指针的比较:

    1. 引用在创建时必须初始化;
    2. 不存在null引用;const int& rInt = 0; //实质上是创建一个临时的int对象,初始化为0,然后再用它来初始化引用rInt,该临时对象将会一直保留到rInt被销毁。
    3. 引用一旦被初始化指向某个对象,它就不能被改变为另一个对象的引用;
    4. 引用的创建和销毁并不会调用类的拷贝构造函数和析构函数;

引用主要用于修饰函数的形参和返回值;

8.C++/C高级数据类型;

在C++语言中,struct成员的默认访问权限限定符为public,class成员的默认访问权限为private。

位域:

可以定义非具名的位域成员,其作用是占位符,可以用来隔离两个相邻的位域成员:

struct Datetime

{

unsigned int day :5;

unsigned int :2;//该成员没有名字,因此不能直接访问它所在的位

unsigend int hour :5;

};

也可以定义长度为0的位域成员,其作用是迫使下一个成员从下一个完整的机器字(word)开始分配空间:

struct Datetime

{

unsigned int day :5;

unsigned int :0;

unsigend int hour :5;

};

cout

注意字节对齐问题;按照从大到小的顺序从前到后依次声明每一个数据成员,并且尽量使用较小的成员对齐方式。

使用offsetof宏来计算数据成员相对于对象起始地址的真实偏移量。

在标准c中,枚举类型的内存大小等于sizeof(int),但是在标准C++中,枚举类型内存大小不一定是sizeof(int),会根据枚举量的取值范围大小,灵活确定。

C++实现了面向对象的I/O系统,不再让用户直接使用“文件指针”这种原始的设施,二是把任何文件看做一个对象,对该对象的操作就是在对一个文件进行操作,同时允许用户为自定义数据类型定制I/O操作。

9.C++/C编译预处理;

带参数的宏定义不是函数,因此没有函数调用的开销,但是其每一次扩展都会生成重复的代码,结果使可执行代码体积增大。

构串操作符#只能修饰带参数的宏的形参,它将实参的字符序列(而不是实参代表的值)转换成字符串常量。例如:

#define STRING(x) #x #x #x

#define TEXT(x) "class" #x "Info"

那么宏引用:

int abc = 100;

STRING(ABC)

TEXT(abc)

展开后的结果分别是:

"abcabcabc"

"classabcInfo"

合并操作符##将出现在其左右的字符序列合并成一个新的标识符(注意,不是字符串)。

10.C++/C文件结构和程序版式;11.C++/C应用程序;

项目的目录结构,文件结构要合理,很重要。

代码风格要统一。

12.C++面向对象程序设计;

含有纯虚函数的类被称为抽象类(抽象基类);

1、定义一个函数为虚函数,不代表函数为不被实现的函数。

2、定义他为虚函数是为了允许用基类的指针来调用子类的这个函数。

3、定义一个函数为纯虚函数,才代表函数没有被实现。

4、定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。

5、一般而言纯虚函数的函数体是缺省的,但是也可以给出纯虚函数的函数体(此时纯虚函数仍然为纯虚函数,对应的类仍然为抽象类,还是不能实例化对象)调用纯虚函数的方法为:抽象类类名::纯虚函数名(实参表)

抽象类的主要用途是“接口与实现分离”:不仅要把数据成员(信息)隐藏起来,而且还要把实现完全隐藏起来,只留一些接口给外部调用。

抽象类把数据和函数实现都隐藏在实现类中,而在抽象类中提供丰富的接口函数供调用,这些函数都是public的纯虚函数。

由于抽象类不能实例化,并且实现类被完全隐藏,所以必须以其他途径使用户能够获得实现类的对象,比如提供入口函数类动态创建实现类的对象。入口函数可以是全局函数,但最好是静态成员函数。

程序中通过基类指针或引用对虚函数的调用语句都会被编译器改写成下面这种形式:

(*(p->_vptr[slotNum]))(p,arg-list);//指针当做数组来用,最后改写为指针运算

其中,p是基类指针,vptr是p指向的对象的隐含指针,而slotNum就是调用的虚函数在vtable中的编号,这个数组元素的索引号在编译时就确定了下来,并且不会随着派生层次的增加而改变。

派生类定义中的名字(对象或者函数名)将义无反顾地遮蔽(既隐藏)掉基类中任何同名的对象或函数。

不要在数组中直接存放多态对象,而是换之以基类指针或者基类的智能指针。使用基类指针可能需要自己负责删除它们指向的对象,但是智能指针不需要。

普通指针:

智能指针:

构成对象本身的只有数据,任何成员函数都不隶属于任何一个对象,非静态成员函数与对象的关系就是绑定,绑定的中介就是this指针。

一个函数名字后有const,这个函数必定是成员函数,也就是说普通函数后面不能有const修饰,如:int print( ) const {.......} 这个函数必定为成员函数,即在类里面定义的函数。在一个类里定义了一个const成员函数后,则此函数不能修改类中的成员变量,如果定义了一个类的const对象(非const对象可以调用const成员函数和非const成员hanshu ),它只能调用类中的const成员函数

explicit可以阻止构造函数的隐式转换,但是只能对含有一个参数,或者有n个参数,但是其中 n-1 个参数是带有默认值的构造函数有效,其余的构造函数,explicit无法进行约束。

类的静态数据成员可以在class的定义中直接初始化,这只是声明它并提供了一个初值而已,还必须在某一个编译单元中把它定义一次(分配内存)。

静态成员最大的特点就是没有this指针,因此可以通过作用域解析运算符(::)直接引用。

13.对象的初始化、拷贝和析构;

每个类只有一个析构函数,但可以有多个构造函数(包含一个拷贝构造函数,其他的是普通构造函数)和多个赋值函数(包含一个拷贝赋值函数,其他的为普通赋值函数)。

构造函数初始化列表的使用规则如下:

    1. 如果类存在继承关系,派生类可以直接在其初始化列表里调用基类的特定构造函数以向它传递参数,因为我们不能在初始化对象时访问基类的数据成员;
    2. 类的非静态const数据成员和引用成员只能在初始化列表里初始化,因为它们只存在初始化语义,而不存在赋值语义;
    3. 类的数据成员的初始化可以采用初始化列表或函数体内赋值两种方式,这两种方式的效率不同,初始化列表的方式效率更高;

数据成员的初始化次序完全不受它们在初始化列表中出现次序的影响,只由它们在类中声明的次序决定。

默认构造函数:参数列表为void或所有参数都有默认值的构造函数;

拷贝构造函数:第一个参数为本类对象的引用、const引用、volatile引用或const volatile引用,并且没有参数,或其他参数都有默认值;

C++中的任何字符串长度至少为1(即至少包含一个结束符“0/”),空字符串也是有效的字符串,因此它代表一块合法的内存单元而不是NULL(注意,STL的std::string不一定包含“0/”)。

通过调用拷贝构造函数类实现拷贝赋值函数,可以确保在拷贝构造函数抛出异常的情况下立即终止赋值操作,因此不会修改左值对象。

派生类的构造函数应在其初始化列表里显式的调用基类的构造函数;

如果基类是多态类,那么必须把基类的析构函数定义为虚函数,否则有可能造成内存泄漏;

在编写派生类的赋值函数时,要对基类的数据成员重新赋值,通过调用基类的赋值函数来实现。

构造函数、析构函数和赋值函数是任何类中最重要的三个函数。

14.C++函数的高级特性;

对比C语言的函数,C++增加了重载,内联,const和virtual四种机制。其中,const和virtual只能用于类的成员函数。

成员函数被重载的特征是:

具有相同的作用域(即同一个类定义中);

函数名相同;

参数类型、顺序或数目不同(包括const参数与非const参数)

virtual关键字可有可无;

覆盖是指派生类重新实现了基类的成员函数,其特征是:

不同的作用域(分别位于派生类与基类中);

函数名相同;

参数列表完全相同;

基类函数必须是虚函数;

隐藏是指派生类的成员函数遮蔽了与其同名的基类成员函数,具体规则如下:

派生类的函数与基类的函数同名,但参数列表不同,此时,不论有无virtual关键字,基类的函数在派生类中将被隐藏(注意与重载的区别);

派生类的函数与基类函数同名,参数列表也相同,但是基类函数没有virtual关键字,此时,基类的函数在派生类中将被隐藏(注意与覆盖的区别)。

运算符重载的特殊性:

如果重载为成员函数,则this对象发起对它的调用;

如果重载为成员函数,则第一个参数发起对它的调佣;

禁止用户发明该语言运算符集合中不存在的运算符;

除了函数调用运算符"()"外,其他运算符重载函数不能有默认参数值;

不要改变重载运算符的语义,要与其内置语义保持一致;

某些运算符之间可以相互推导,比如在逻辑运算符之间和关系运算符之间,我们可以只实现少数几个运算符,然后用它们来实现其他运算符。

重载“++”和“--”:

C++语言的函数内联机制:

对于任何内联函数,编译器在符号表里放入函数的声明,包括名字,参数类型,返回值类型。如果编译器没有发现内联函数存在错误,那么该函数的代码也被放入符号表里。在调用一个内联函数时,编译器首先检查调用是否正确,如果正确,内联函数的代码就会直接替换函数调用语句,于是省去了函数调用的开销。

C++程序中应该尽量用内联函数取代宏代码,除了断言。

关键字inline必须与函数定义放在一起,放在函数声明前无作用。推荐函数声明中不要出现inline关键字,无论它是否为内联函数,用户无需知道该函数是否内联。

类型转换的本质是创建新的目标对象,并以源对象的值来初始化,所以源对象没有丝毫改变,不要把类型转换理解为“将源对象的类型转换为目标类型”。

类型转换运算符定义以operator关键字开始,紧接着目标类型名和()。它没有参数,实际上this就是参数;也没有返回类型,实际上函数名就是返回类型。它只能定义为非静态成员函数。

C++新增了4个类型转换运算符:

static_cast(src_obj),作用相当于C风格的强制转换,但是在多重继承的情况下,它会正确的调整指针的值,而C风格的强制转换则不会调整;他可以遍历继承树来确定src_obj与dest_type的关系,但是只在编译时进行(此所谓静态);如果使用它来做downcast操作,则会存在隐患;

const_cast(src_obj),用于去除一个对象的const/volatile属性;

reinterpret_cast(stc_obj),我们可以借助它把一个整数转换成一个地址,或者在任何两种类型的指针之间转换。使用该运算符需要十分小心。

dynamic_cast(src_obj),在运行时遍历继承树(类层次结构)来确定src_obj与dest_type的关系。

任何不会修改数据成员的成员函数都应该声明为const类型。如果在编写const成员函数时不慎写下了视图修改数据成员的代码,或者调用了其他非const成员函数,编译器将会报错。

15.C++异常处理和RTTI;

异常处理也是一种程序控制结构,它包括4个组成部分:抛出异常、提炼异常、捕获异常以及异常对象本身。他们对应了C++的3个关键字及其构造,即throw、try{}、catch{}。throw只是一条语句,而try和catch各引导一个程序块,即使它们是空的。try{}块包含了可能会有异常抛出的代码段,而catch{}块则包含用户定义的异常处理代码。一条throw语句只能抛出一个异常,一个catch子句也只能捕获一种异常。

异常对象并非创建在函数堆栈上,而是创建在专用的异常堆栈上。

C++的异常对象与catch子句的匹配规则:

catch子句参数的类型就是异常对象的类型或其引用;

catch子句参数类型是异常对象所属类型的public基类或其引用;

catch子句参数类型为public基类指针,而异常对象为派生类指针;

catch子句参数类型为void * ,而异常对象为任何类型指针;

catch子句为catch-all,即catch(...)。

当异常抛出时,异常处理机制保证:所有从try到throw语句之间构造起来的局部对象的析构函数将被自动调用(以与构造相反的顺序),然后清退堆栈。但是如果一直上溯到main函数后还没有找到匹配的catch块,那么系统会调用terminate函数终止整个程序,这种情况下,不能保证所有的局部对象会被正确销毁。

在析构函数中抛出异常较为危险,更合理的方法是在析构函数中就地处理掉所有异常。

typeid()运算符就像sizeof()运算符一样是C++语言直接支持的,它以一个对象或者类型名作为参数,返回一个匹配的const type_info对象,它标明该对象的确切类型。

dynamic_cast<>运算符用来执行运行时类型识别和转换,其语法如下:

dynamic_cast(src);

其中,dest_type就是转换目标类型,而src则是被转换的对象。其行为可以这样描述:如果运行时,src和dest_type确实存在is-a关系,则转换成功,否则转换失败;

dynamic_cast<>可以用来转换指针和引用,但是不能转换对象。当目标类型是某种类型的指针(包括void*)时,转换成功则返回目标类型的指针,否则返回NULL;当目标类型为某种类型的引用时,转换成功,则返回目标类型的引用,否则抛出std::bad_cast异常,因为不存在NULL引用。

dynamic_cast<>智能用于多态类型对象(拥有虚函数或者虚拟继承),否则将导致编译错误。

16.内存管理;

对指针进行free()或者delete操作之后,只是释放了对应的内存,指针本身值没有改变,应同时置为NULL;

new和delete运算符会调用对象的构造和析构函数,而malloc()和free()库函数不会。

智能指针:

  • auto_ptr智能指针:(C++11出来前只有这种智能指针)当对象拷贝或者赋值后,前面的对象就悬空了。
  • unique_ptr智能指针:防止智能指针拷贝和复制。
  • shared_ptr智能指针:通过引用计数的方式来实现多个shared_ptr对象之间共享资源。
  • weak_ptr智能指针:可以从一个shared_ptr或另一个weak_ptr对象构造,它的构造和析构不会引起引用记数的增加或减少。

注意:每一种智能指针都可以增加内存的引用计数。

  • 智能指针分为两类:

    • 一种是可以使用多个智能指针管理同一块内存区域,每增加一个智能指针,就会增加1次引用计数,
    • 另一类是不能使用多个智能指针管理同一块内存区域,通俗来说,当智能指针2来管理这一块内存时,原先管理这一块内存的智能指针1只能释放对这一块指针的所有权(ownership)。
  • 按照这个分类标准,auto_ptr unique_ptr weak_ptr属于后者,shared_ptr属于前者。

对shared_ptr进行初始化时不能将一个普通指针直接赋值给智能指针,因为一个是指针,一个是类。可以通过make_shared函数或者通过构造函数传入普通指针。并可以通过get函数获得普通指针。

17.学习和使用STL;

vector 向量容器

当需要使用动态分配的数组的情况下,可以考虑使用vector,当删除元素时,不会释放限制的空间,所以向量容器的容量(capacity)大于向量容器的大小(size)。

头文件:#include

vector<int> myvector;

常用函数一览:

v.capacity(); //容器容量

v.size(); //容器大小

v.at(int idx); //用法和[ ]运算符相同

v.push_back(); //尾部插入

v.emplace_back(); //尾部插入,效率更高

v.pop_back(); //尾部删除,注意括号里不用加参数!

v.front(); //获取头部元素

v.back(); //获取尾部元素

v.begin(); //头元素的迭代器

v.end(); //尾部元素的迭代器

v.insert(iterator,elem); //在iterator指向的位置前插入值为elem的元素,返回指向这个值的迭代器。

v.insert(iterator, n, elem) //在iterator指向位置前插入n个值为elem的元素 v.insert(iterator, v2.begin, v2.end); //在v的iterator指向位置前,插入v2的[begin, end)区间的所有元素

v.erase(iterator); //移除iterator指向位置上的元素,迭代器此时指向下一个元素,但是迭代器指向位置不变

v.erase(begin, end); //移除[begin, end)区间的数据,迭代器此时指向下一个元素,但是迭代器指向位置不变

v.reverse(pos1, pos2); //将vector中的pos1~pos2的元素逆序存储

《高质量程序设计指南》读书笔记相关推荐

  1. 读书笔记 | 墨菲定律

    1. 有些事,你现在不做,永远也不会去做. 2. 能轻易实现的梦想都不叫梦想. 3.所有的事都会比你预计的时间长.(做事要有耐心,要经得起前期的枯燥.) 4. 当我们的才华还撑不起梦想时,更要耐下心来 ...

  2. 读书笔记 | 墨菲定律(一)

    1. 有些事,你现在不做,永远也不会去做. 2. 能轻易实现的梦想都不叫梦想. 3.所有的事都会比你预计的时间长.(做事要有耐心,要经得起前期的枯燥.) 4. 当我们的才华还撑不起梦想时,更要耐下心来 ...

  3. 洛克菲勒的38封信pdf下载_《洛克菲勒写给孩子的38封信》读书笔记

    <洛克菲勒写给孩子的38封信>读书笔记 洛克菲勒写给孩子的38封信 第1封信:起点不决定终点 人人生而平等,但这种平等是权利与法律意义上的平等,与经济和文化优势无关 第2封信:运气靠策划 ...

  4. 股神大家了解多少?深度剖析股神巴菲特

    股神巴菲特是金融界里的传奇,大家是否都对股神巴菲特感兴趣呢?大家对股神了解多少?小编最近在QR社区发现了<阿尔法狗与巴菲特>,里面记载了许多股神巴菲特的人生经历,今天小编简单说一说关于股神 ...

  5. 2014巴菲特股东大会及巴菲特创业分享

     沃伦·巴菲特,这位传奇人物.在美国,巴菲特被称为"先知".在中国,他更多的被喻为"股神",巴菲特在11岁时第一次购买股票以来,白手起家缔造了一个千亿规模的 ...

  6. 《成为沃伦·巴菲特》笔记与感想

    本文首发于微信公众帐号: 一界码农(The_hard_the_luckier) 无需授权即可转载: 甚至无需保留以上版权声明-- 沃伦·巴菲特传记的纪录片 http://www.bilibili.co ...

  7. 读书笔记002:托尼.巴赞之快速阅读

    读书笔记002:托尼.巴赞之快速阅读 托尼.巴赞是放射性思维与思维导图的提倡者.读完他的<快速阅读>之后,我们就可以可以快速提高阅读速度,保持并改善理解嗯嗯管理,通过增进了解眼睛和大脑功能 ...

  8. 读书笔记001:托尼.巴赞之开动大脑

    读书笔记001:托尼.巴赞之开动大脑 托尼.巴赞是放射性思维与思维导图的提倡者.读完他的<开动大脑>之后,我们就可以对我们的大脑有更多的了解:大脑可以进行比我们预期多得多的工作:我们可以最 ...

  9. 读书笔记003:托尼.巴赞之思维导图

    读书笔记003:托尼.巴赞之思维导图 托尼.巴赞的<思维导图>一书,详细的介绍了思维发展的新概念--放射性思维:如何利用思维导图实施你的放射性思维,实现你的创造性思维,从而给出一种深刻的智 ...

  10. 产品读书《滚雪球:巴菲特和他的财富人生》

    作者简介 艾丽斯.施罗德,曾经担任世界知名投行摩根士丹利的董事总经理,因为撰写研究报告与巴菲特相识.业务上的往来使得施罗德有更多的机会与巴菲特亲密接触,她不仅是巴菲特别的忘年交,她也是第一个向巴菲特建 ...

最新文章

  1. 应用程序启动器 标记为信任_为什么您今天不能信任应用程序-以及如何解决它...
  2. C# 数据库连接笔记
  3. 华人Hbuy隐私政策
  4. JS版数据结构第三篇(链表)
  5. 【Java报错】借助@PostConstruct解决使用@Component注解的类用@Resource注入Mapper接口为null的问题(原因解析+解决方法)
  6. 加拿大上市矿企Bitfarms完成第二笔1500万美元普通股私人认购
  7. 【To Do!】程序员面试金典——11.8维护x的秩
  8. day 3 - 1 数据类型
  9. 自考《离散数学》题型总结
  10. Linux下安装qt5步骤
  11. 什么是微网格?微网格规划应考虑哪些因素?
  12. 使用opencv测量点到线的距离
  13. 傲腾服务器系统,服务器加傲腾内存
  14. 05【实操篇-文件目录类命令】
  15. JavaEE|IO、存储、硬盘、文件系统相关常识
  16. 软件测试学习笔记(九)淘宝测试
  17. 霍夫变换(Hough)
  18. 《Thinking In Java》作者:不要使用并发!
  19. ubuntu20.04开机后出现 /dev/sdb3 xxx files xxxx/xxxxx blocked,无法进入桌面问题
  20. 用Java写一款小游戏

热门文章

  1. Hive,Pig,HBase 傻傻分不清楚
  2. C# xml压缩包不解压的情况下解析xml内容
  3. centos配置maven环境
  4. Python之random.seed()用法
  5. ubuntu 安装docker_Docker学习笔记1 虚拟化历史及 Ubuntu环境下体验安装
  6. Boxfilter 块滤波器
  7. qt自定义QtWidgets
  8. 利用C++的stringstream对各种数据类型转换
  9. python hello world程序编写_自动编写Python程序的神器,Python 之父都发声力挺
  10. html请求接口_Python 如何使用 HttpRunner 做接口自动化测试