您的位置:首页 > 编程语言 > C语言/C++

C++ Primer学习系列(1):快速入门/变量和基本类型/标准库类型

2016-07-29 00:00 369 查看
序:
为再复习一下以前的学习内容,也为了不断地提高自己,我决定把以前的学习笔记整理出来汇成一个系列,使自己形成一个知识体系。整个系列大概有7到8个部分,每个部分一般有3章的内容。笔记中有的是书中重点内容的重新再现(我用了精简而又易于理解的语言来描述),有的是我自己的理解(不一定完全正确,希望大家多多指教),有的是我作的总结。学习时只有不断地总结才会把书读薄,才会有质的提高,这是我学习过程中最深刻的体会。

1 章 快速入门
写程序的一般步骤:定义数据结构保存数据、定义函数、定义变量、实现处理逻辑、实现输入输出
1.1
main函数由操作系统调用, main函数执行完时返回一个值给操作系统,返回 0表示成功执行。记住: main函数是唯一被操作系统显示调用的函数 ;main函数返回类型必须是 int型
函数的 4个元素:返回类型、函数名、圆括号内的形参表、函数体
return返回值的类型必须和函数返回类型相同或者可以转换成函数的返回类型
1.2
iostream库:类 istream,ostream
标准输入: istream类对象 cin
标准输出: ostream类对象 cout。读 cin会刷新 cout,当程序正常结束时也会刷新 cout。
标准错误: ostream类对象 cerr。默认情况下 cerr不缓冲。
标准日志: ostream类对象 clog。默认请问下写到 clog时带缓冲。
命名空间: C++标准库定义 的名字在命名空间 std中
#include指示必须单独写成一行:头文件名和 #include必须在同一行
输出操作符 <<:将右操作数写到左操作数 ostream对象中,返回左操作数。注意 cout<<”Enter two nubmers:”是一个表达式,其返回结果是左操作数的值(即输出流 cout本身),因此输出请求可以链接在一起;由操作符重载知 <<相当于一个函数,传入实参是两个操作数,返回值是表达式结果。
操纵符 endl:换行,会刷新输出流(理解:即刷新与设备相关的缓冲区)
作用域操作符” ::”: std::cout表示使用命名空间 std中的 cout
输入操作符 >>:从左操作数 istream对象中读取数据保存到右操作数对象中,并返回左操作数
iostream库定义了接受全部内置类型的输入输出操作符
1.3
注释:任何允许有制表符、空格或换行符的地方都允许放注释对 /*与 */;单行注释为 //。记住注释对不可以嵌套
1.4
C++中的块:用花括号括起来的语句序列。在任何可以用一条语句的地方都可以用块
标准 C++中, for语句头中定义的计数变量是局部的, for循环结束后这个变量不可访问,而以前版本的 C++中是可访问的
使用 istream对象作为测试条件:测试的是流的状态,若流是有效的(即读入下一个输入是可能的),则测试成功;遇到文件结束符或无效输入时,测试失败。
文件结束符的键入: Windows中键入 Ctrl+ z, Unix/Linux/Mac Os中键入 Ctrl+d
1.5
内置类型: C++内建的数据类型,如 int,char等
类类型:用 class c_name定义的类 c_name可理解为一种新的数据类型( c_name类型),可以像使用 int,long,char等内置类型一样使用 c_name类型来定义变量
头文件的引入:标准库的头文件用 < >括起来,非标准库的头文件用双引号” “括起来
对象相加:执行的是两个对象的成分相加,要用到操作符重载
成员函数:也称为类方法,是由类定义的函数,只定义一次,但被视为每个对象的成员。 C++中还有继承自 C的普通函数,不属于任何类
点操作符” .”:用于调用成员,左操作数是类类型的对象,右操作数是该类型的成员名。通过左操作数取得右操作数
调用操作符 ():在调用函数时放在函数名后面,括住要传入的实参列表(可能为空)
总结:
main函数、标准 I/O对象、命名空间、输出操作符 <<和输入操作符 >>、注释、头文件的导入、成员函数、点操作符 .、调用操作符 ()

2 章 变量和基本类型
2.1
动态类型语言:在运行时才执行类型检查,结果可以直接使用一个变量,无需事先定义,如 Smalltalk,Python
静态类型语言:在编译时执行类型检查,结果是程序使用某个名字前,必须告知编译器该名字的类型,如 C++
基本内置类型:包括算术类型(整数、浮点数、字符、布尔值)和 void特殊类型, C++标准定义了每个算术类型的最小存储空间,但并不阻止编译器使用更大的空间
void类型:没有对应值,常用于无返回值函数的返回类型
整型: bool,char,wchar_t,short,int,long。通常 short为半个机器字长, int为一个机器字长, long为一个或两个机器字长(在 32位机中通常为一个机器字长)。除 bool类型外,整型可以是 signed的(默认情况),也可以是 unsigned的, unsigned int可简写成 unsigned。
char有三种不同的类型:普通 char,unsigned char和 signed char,但只有两种表示方式,普通 char是 signed的还是 unsigned的由编译器而定
整型的赋值:将超过范围的值赋给 unsigned类型时,编译器会将该值对 unsigned的可能取值数目求模,然后取所得值(实际上就是截断处理,截取低位)。因此把 -1赋给 8位的 unsigned char,结果是 -1%256= 255。若赋给 signed类型,由编译器决定实际赋的值。但大多数编译器的处理方式与 unsigned类型相似。
浮点型: float,double,long double。通常 float32位, double64位, long double96或 128位。
2.2
字面值常量: long型后加 L,单精度型后加 F,扩展精度后加 L, wchar_t型前加 L,无符号常量后加 U。浮点型常可用十进制或科学记数法表示
转义字符: /n,/v,/r,/a,/?,/”,/t,/b,/f,//,/',也可用八进制形式 /ooo。 '/0'表示空字符 null,同样也可用十六进制形式 /xddd
字符串字面值:为了兼容 C, C++中所有的字符串常量都由编译器自动在末尾添加一个空字符
宽字符串常量:在字符串前面加 L
字符串常量的连接: C++标准没有定义连接不同类型字符串(如字符串和宽字符串)的行为
2.3
C++中的两种表达式:左值是变量的地址,可以出现在赋值语句的左边或右边;右值是变量的值,只能出现在赋值的右边
赋值操作符 =:读取右操作数并写到左操作数中,左操作数之前的值被覆盖
变量初始化的两种形式:复制初始化(用等号)、直接初始化(用圆括号)。注意初始化与赋值是两种不同的操作,初始化指创建变量并给它赋初始值,而赋值则是擦除对象的当前值并用新值代替
当初始化类类型对象时,复制初始化和直接初始化有差别。而对内置类型来说,它们几乎没有差别。记住直接初始化语法更灵活且效率更高
内置类型变量的初始化:全局变量都初始化成 0,函数里的局部变量不进行自动初始化
类类型变量的初始化:由构造函数来控制类对象的初始化。用户定义对象时若没有进行初始化,类会用默认构造函数来初始化。类中一般要定义默认构造函数,若类没定义默认构造函数,则定义对象时必须显示地初始化
声明和定义:变量的定义要分配存储空间,而声明只是表明变量的类型和名字,并不分配存储空间。用 extern声明变量时不是定义,也不分配存储空间,它只是说明变量定义在程序的其他地方。程序中变量可以声明多次,但只能定义一次。
extern声明变量若进行了初始化,则可当作是定义,只有当 extern声明位于函数外部时,才可以含有初始化式(即 extern定义的只能是全局变量)
C++中的作用域:全局作用域、局部作用域、语句作用域、类作用域、命名空间作用域。作用域可嵌套,即大作用域在其里面的小作用域内可见。记住变量从声明开始才可见。
2.4
const限定符:指定变量为常量,定义后就不能被修改,因此定义时必须初始化。
如: const int i=1
全局作用域中的非 const变量默认为 extern,可以在其他文件中访问;而 const变量默认是局部于文件的,要想在其他文件中访问,必须显示地指定它为 extern
2.5
引用:变量或对象的另一个名字,通过在变量前添加&来定义,主要用于函数的形参。引用是一种复合类型(即用其他类型定义的类型),必须关联到某一其他类型,不占内存空间。引用在定义时就必须用同类型的变量来初始化,普通引用不能用常量来初始化。如 int ival=20;int &refVal=ival;不能 int &ref=40;
引用初始化后,就一直指向这个对象,不可再指向其他对象
const引用:是指向 const对象的引用。 const引用是只读的,必须指向 const变量,不能通过 const引用来修改其指向的变量值。注意非 const引用不能指向 const变量。 const引用可以用常量来初始化。可见非 const引用是指向非 const对象的引用
非 const引用只能绑定到与该引用同类型的对象; const引用可以绑定到不同但相关的类型的对象或绑定到右值(如常量)。原因:
double dval=3.14;
const int &ri=dval;
编译器会把代码转换成如下形式:
int temp=dval;
const int &ri=temp;
倘若 ri不是 const,那么不能达到通过 ri来修改 dval的目的 (修改的是 temp),因此非 const引用不能指向不同类型的对象;而 ri是 const时, ri是只读的,不可写,因此 const引用指向不同类型的对象时是允许的,不会违背设计初衷
2.6
typedef名字:定义类型的同义词,并没有引入新的类型。通常用于隐藏特定类型的实现,强调使用类型的目的;简化复杂的类型定义,使其更易理解;以及允许一种类型用于多个目的。
2.7
枚举类型:用 enum定义枚举类型,里面的每个枚举成员都会初始化,或者显示初始化,或者隐式初始化。如 enum Forms {shape=1,sphere,cylinder,polygon};注意枚举成员是一个常量,值不能改变。枚举类型对象的初始化或赋值,只能通过其枚举成员或同一枚举类型的其他对象来进行。
2.8
记住:自定义类型时末尾有一个 分号
类类型:用 class定义,有一个接口(类定义)和一个实现(类实现)。类定义中有数据成员和成员函数。
定义变量和定义数据成员的区别:数据成员的初始化一般不放在类定义中,类定义中只指明成员的名字和类型,成员的初始化一般放在构造函数中
结构类型:用 struct定义。定义的类与 class相同,唯一的区别在于 struct的成员默认为 public, class的成员默认为 private。
2.9
分别编译:一个程序可以有多个头文件,多个源文件, C++支持分别编译。
头文件:头文件包含在多个源文件中,所以不应该含有变量或函数的定义。头文件中一般放类定义、值在编译时就已知的 const对象、 inline函数。当然,这些实体也可以在多个源文件中定义,只要每个源文件中的定义是相同的。普通变量、成员函数、普通函数等放在单独的源文件中
常量表达式:编译器在编译时就能够计算出结果的表达式(如 3.14, 1+2)。
有些 const对象定义在头文件中的原因:用常量表达式进行初始化的 const变量,初始化式就必须为编译器可见。为了能让多个文件使用相同的常量值, const变量和它初始化式必须是每个文件都可见的,因此要定义在头文件中,如 const double pi=3.1416。有人问任何变量都只能定义一次,那头文件中的 const变量不是会被各源文件多次定义吗?实际上 const对象默认为文件局部对象,这表明每个包含头文件的源文件都有了自己的 const变量,互不影响,因此在头文件中定义 const变量是合法的。
若 const变量不是用常量表达初始化的,则不应该放在头文件中,如 const double sq2=squt(2,0)
预处理器:如 #include,#define,#ifdef...#endif,在编译之前运行
头文件保护符:防止在源文件中多次包含同一头文件的内容(多重包含)
最佳实践:头文件应该含有保护符,即使这些头文件不会被其他头文件包含。这样可以避免难以理解的编译错误
#ifndef SALESITEM_H
#define SALESITEM_H
//...
#endif

总结:
内置类型(整型 6种,浮点型 3种, void类型)、复合类型(引用, typedef名字,指针、数组)、自定义类型( class,struct,enum)、常量、变量(变量定义, extern声明,变量初始化)、作用域、 const引用和 const变量、预处理器、头文件保护符

3 章 标准库类型
3.1
using声明:声明命名空间中的名字定义,注意末尾要加分号
using指示:指定要使用的名字空间,如 using namespace std;
有一种情况必须完全使用限定的标准库名字:在头文件中。在头文件中一般不包含 using声明,因为这样的话包含该头文件的每个源文件都有 using声明,而不论源文件是否需要这个 using声明
3.2
标准库 string类型:
#include <string>
using std::string
string对象的初始化: s1,s2(s1),s3(“value”),s4(n,'c')
读取整行文本:用 getline(cin,string)函数,在 <string>头文件中定义
string对象的操作: empty(),size(),s
,s1+s2,s1=s2,及 ==,!=,<,<=,>,>=,+=等
size()返回值的类型:为 string::size_type类型,它是 unsigned的,注意不要赋给 int变量
当进行 string对象和字符串字面值混合连接操作时, +操作符的左右操作数必须至少有一个是 string类型的
注意:为了与 C语言兼容,字符串常量与 string不是同一种类型
string对象的下标操作符 []: s
,n是 string:size_type类型。下标操作可用作左值
字符处理函数:在 cctype(对应 C标准库中的 ctype.h头文件)头文件中定义,可以对 string对象中的字符进行处理。 isalnum(c),isalpha(c),iscntrl(c),isdigit(c),isgraph(c),islower(c),isprint(c),ispunct(c),isspace(c),isupper(c),isxdigit(c),tolower(c),toupper(c)
3.4
标准库 vector类型:
#include <vector>
using std::vector;
vector不是一种数据类型,而是一个类模板,可用来定义任意多种数据类型。 vector<int>才是数据类型
vector对象定义和初始化: vector<T> v1,v2(v1),v3(n,i),v4(n)
vector对象的操作: empty(),size(),push_back(t),v
,=,==,!=,<,<=,>,>=等
size()返回值的类型:为 vector<T>::size_type类型,而不是 vector::size_type
容器的 iterator类型:标准库为每一种标准容器定义了一种迭代器类型。如 vector<int>::iterator。 iterator类型变量相当于一个指针,指向容器中的元素,可以对指针进行自增操作
容器的 begin()和 end()操作:返回容器的迭代器
vector迭代器的自增和解引用操作:如 vector<int>::iterator iter; *iter=0;解引用操作用来访问容器中的元素。解引用操作返回左值
注意: end()操作返回的迭代器不指向任何元素,因此不能进行自增或解引用操作
iterator的比较操作: ==,!=,判断 iterator是否指向同一个元素
容器的 const_iterator类型:只能读取容器内的元素值,不能改变元素值。对 const_iterator类型解引用时得到一个指向 const对象的引用。注意 const_iterator变量相当于一个指针,它自身的值可以改变(移动指针),但不能用来改变其所指向的元素的值。
如:
for(vector<string>::const_iterator iter=text.begin();
iter!=text.end();++iter)
cout<<*iter<<endl; //* iter是 const引用,即指向 const对象的引用
const的 iterator对象:如 const vector<int>::iterator cit=nines.begin();是一个 const变量,定义时必须初始化,之后变量自身的值不可改变,但其指向的元素值可以改变,如 *cit=10。因此当我们不想改变容器内元素的值时,不能用 const的迭代器来访问元素,而要用 const_iterator迭代器来访问元素,这也是引入 const_iterator类型的原因。
const容器:是指容器内的元素值不可改变。因此不能从 const容器返回 const的迭代器,但可以返回 const_ iterator迭代器
vector<int> vec(10,9);
const vector<int> nines(10,9); //不能改变 nines中的元素值,因为 nines是 const对象,
//表明这块内存区域值不能改变,故区域中的元素值不能改变
const vector<int>::iterator cit=nines.begin(); //error:因为 *cit是非 const的,指
//向了 const的内存区域中的某个值
vector<int>::const_iterator it=nines.begin(); //ok
*it=10; //error:因为 *it是 const的,不能重新赋值
++it; //ok
vector<int>::const_iterator it2=vec.begin(); //ok: vec对象本身不是常量,但通过
//*it2访问到的对象是常量
记住:( 1) cit是 const的, *cit是非 const的; it是非 const的, *it是 const的;( 2) const_iterator对象可以用于 const vector或非 const vector,因为不能改写元素值
vector迭代器的算术操作: iter++,iter+n返回的是 vector的 size_type类型; iter-n,iter1-iter2返回的是 vector的 difference_type类型(是 signed的)。注意没有定义两个迭代器相加的操作 iter1+iter2,因此定位中间元素可用 vi.begin()+vi.size()/2,但不可用 (vi.begin()+vi.end())/2
3.5
标准库 bitset类型:
#include <bitset>
using std::bitset;
bitset对象的定义和初始化: bitset<n> b,b(u),b(s),b(s,pos,n)
用 unsigned long值初始化 bitset对象:多出的位作截断处理
string对象初始化 bitset对象: string对象最右边的字符用来初始化 bitset对象的低阶位
bitset对象上的操作: any(),none(),count(),size(),b[pos],test(pos),set(),set(pos),reset(),reset(pos),flip(),flip(pos),to_ulong(),os<<b
size(),count()返回值类型:为 size_t标准库类型,是 unsigned的,在 <cstddef>中定义
to_ulong()操作:把 bitset对象转到 C风格的程序上,若 bitset包含的二进制位数超过 unsigned long的长度,将会产生运行时异常
总结:
标准库类型 string,vector,bitset的操作
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: