c++ Primer 第1~4章部分摘写。

来源:互联网 发布:java 并发 lock详解 编辑:程序博客网 时间:2024/05/21 01:51

虽然很基础,但还是有一些收获的。

第一章:

文件结束符。Windows: ctrl+z

                        Unix :ctrl+d

第二章:

2.1基本内置类型

一个字节:8位

一个字:32位或4个字节

short一般位半个机器字长,int为一个机器字长,long在32位机器与int相同字长。


2.3定义对象。

1、初始化。

复制初始化:语法用等号。  int ival=1024;

直接初始化:语法用括号。  int ival(1024);


在函数体外定义的变量都初始化成0,在函数体里定义的内置类型变量都不进行自动初始化。


类类型变量如果没有初始化,则使用默认构造函数。


2、声明和定义

定义:分配存储空间,指定初始值。

声明:表明类型和名字。


3、枚举。

enum Points{point2d=2,point2w,point3d=3,point3w};

Points pt2w =3;//error

Points pt2w = point2w;//ok

Points pt3 = pt2w;//ok


4、头文件

(1)头文件用于声明而不是定义

非const变量不应该在头文件上定义,而应该在源文件定义。因为头文件容易被多次包含在多个源文件中,当放在一起编译的时候,容易造成多重定义。

比如:

extern int ival = 10;

double fica_rate;

(2)const对象定义在头文件中

由于const变量默认是 定义该变量的文件的局部变量!,所以即使一起编译,也不会造成多重定义。


5、预处理器的简单介绍

有时候一个头文件被多次包含在同一个源文件中,这很可能使得头文件中定义的类和对象被多次定义。

于是我们使用预处理器定义 头文件保护符 ,用于避免在已经见到头文件的情况下重新处理该头文件的内容~

例:

#ifndef SALESITEM_H

#define SALESITEM_H

//未发现定义,开始处理头文件的一些内容

.....(t头文件内容)……

#endif


比如我便可以认为 当SALESITEM_H未定义时候,便是我自己写的mymath.h没有被预处理器处理,于是定义SALESITEM_H,并开始处理这个文件。

当再次遇到时候,便已经定义了,于是也不需要执行了。


第三章:标准库类型

3.2标准库类型:string

读写:

例:   string str;

           cin>>str;

1、读取并忽略开头所有空白字符(空格,换行符,制表符)

2、读取字符直至再次遇到空白字符。

输入: “    hello   world”

输出:“hello”


string对象的操作

string str;

str.empty();  //s为空串,返回true。否则返回false

str.size(); //返回字符串的个数  返回类型为string::size_type


string对象字符的处理

#include <cctype> 

见《C++ Primer 中文版(第四版)》 P77页


3.3、标准库vector类型

#include <vector>

using std::vector;


使用方法:

vector<int> ivec;

class Student{};

vector<Student> stu;


初始化

vector<T> v1;

vector<T> v2(v1);

vector<T> v3(n,i)   v3包含n个值为i的元素

vector<T> v4(n)  v4含有值初始化的元素的n个副本


vector对象的操作

vector<T> v;

v.empty();  //检测v是否为空,为空返回true;否则返回false;

v.size(); //返回v中元素的个数

v.push_back(t); //在v的末尾增加一个值为t的元素

v[n]  返回v中位置为n的元素。该操作仅能读取已经存在元素的值,而不能用来添加元素。


3.4迭代器简介。

迭代器实质上是一种类型,每个标准库容器类型中都有一个iterator的成员,这里的iterator与迭代器实际类型相同(iterator类型)

vector<int> ivec;

vector<int>::iterator iter=ivec.begin();  //这里的iterator作为一种元素的类型,定义了一个iter,该变量类型为iterator类型(迭代器类型)

访问迭代器所指向的元素,*iter = 0;


第4章:数组和指针。

4.1数组

数组的维数必须用值不小于1的常量表达式定义。这个常量表达式必须在未编译前就确定的,所以不能是函数返回值。


数组的初始化:

例:

const unsigned array_size=3;

int ia[array_size]={0,1,2};


如果未有显式的提供元素初值,则数组元素会像普通变量一样初始化:

在函数体定义的内置数组,其元素均初始化为0;

在函数体定义的内置数组,其元素均初始化为0;

对于类类型的数组元素,无论在哪里定义,都会自动调用该类的默认构造函数进行初始化,如果该类没有默认构造函数,则必须为该数组的元素提供显式初始化。


特殊的字符数组:


1、两种初始化方式:

(1)用一组由花括号括起来的、逗号隔开的字符 字面值进行初始化。

char ca1[]={'c','+','+'};

char ca2[]={'c','+','+','\0'};

(2)也可以用一个字符串 字面值进行初始化

注意:字符串字面值包含了一个额外的空字符用于结束字符串。

char ca3[]="C++"; //null字符自动加上的


如下例子会编译错误:

char ca3[6]="123456";


4.2指针的引入

1、NULL

预处理器变量NULL,该变量在<cstdlib>头文件中定义,其值为0.编译时候会自动被数值0替换。


2、void *指针

可以保存任何类型对象的地址。


3、计算数组的超出末端指针

C++允许计算数组或者对象超出末端的地址,但不允许对此地址进行解引用操作。


4、指针和const限定符

(1)指向const对象的指针

const doube *cptr;

指向的对象是const的,指针是可以修改的。

意思是我这个cptr永远都会指向我认为是const的变量的地址,但我指向谁是可以变的,我可以选A这个const变量,也可以选B这个const变量,也可以选一个大家认为不是const但我潜意识认为是const的。

上述话语大概取自原书。

也就是说,即使我指向的不是const变量,但前面接了const,我就认为他是,所以我也不能去改这个变量值,即使他不是const。

例:

int a=1;

const int *pt = &a;

*pt=2;//error


(2)const指针

int a=0;

int  *const pt = &a;

指针的指向谁被固定了,至于指向的对象是const还是非const,并没有关系。

能否修改指向的对象的值,得看指向的对象是const还是非const的


5、指针和typedef(易错)

typedef string * pstring;

const pstring cstr;

错误认为:const string* cstr;

正确说法:先改成pstring const cstr;

                                string *const cstr;


4.3C风格字符串(以空字符null结束的字符串组)

记住

char c3[] ="C++";//后面是自动补上null('\0') 维数是4


标准库函数

#include <cstring>


strlen(s)   //返回s的长度,不包括字符串结束符null

其余见《C++ Primer 中文版(第四版)》P114页。


注意:不要忘记,标准库函数strlen总是假定其参数字符串是以null字符结束的。

char ca[]={'c','+','+'}

cout<<strlen(ca)<<endl;


创建动态数组

C语言中使用一对标准库函数malloc和free自由存储区中分配存储空间,C++语言使用new和delete表达式实现相同的功能


new表达式返回新分配数组的第一个元素的指针。

Int *pid=new int[10]


动态分配数组的初始化

(1)如果是类类型,将使用该类的默认构造函数。

例:

string *psa=new string[10];  //初始化为10个空字符串

(2)如果是内置类型,则无初始化

int *pia=new int[10];

此时未有初始化,可以在数组长度后面加上一对空圆括号!

Int *piad=new int[10]();


释放动态分配的数组

delete [] pia;

其中的括号必不可少,它告诉编译器该指针指向的是自由存储区中的数组,而不是单个对象。





0 0