《C++ Primer中文版》(第四版)信息汇总(一)

最近决定把Lippman的大作《C++ Primer》重新温习一遍,在查阅的过程中记录下一些重要的知识点,希望对于自己有一定的帮助。为方便查询,全部内容按照章节分类。

第一章 快速入门
1、iostream库的基础是两种命名为istream何ostream的类型,分别表示输入流和输出流。

标准库定义了4个IO对象,处理输入时使用cin的istream类型对象。处理输出时使用命名为cout的ostream类型对象。处理标准错误的用来输出警告和错误信息给程序的cerr对象。用于产生程序执行的一般信息的clog对象。

2、读入未知数目的输入:利用while语句判断,直到遇到文件结束符(ctrl+z)

view plaincopy to clipboardprint?
while(std::cin>>value)   
    sum+=value;  
while(std::cin>>value)
    sum+=value;

第二章 变量和基本类型
1、复制初始化和直接初始化

view plaincopy to clipboardprint?
int ival(1024);//直接初始化   
int ival=1024;//复制初始化  
int ival(1024);//直接初始化
int ival=1024;//复制初始化

2、初始化不是赋值:初始化是指创建变量并给它赋初始值,而赋值则是擦除对象的当前值并用新值代替。

3、声明和定义:变量的定义用于为变量分配存储空间,还可以为变量指定初始值,在一个程序中,变量有且仅有一个定义;声明用于向程序表明变量的类型和名字,定义也是声明:当定义变量时我们声明了它的类型和名字。可以通过extern关键字声明变量名而不定义它。

view plaincopy to clipboardprint?
extern int i;//声明但没有定义   
int i;//声明并且定义i  
extern int i;//声明但没有定义
int i;//声明并且定义i

4、常量在定义时必须初始化:因为常量在定义后就不能被修改,所以必须初始化。

view plaincopy to clipboardprint?
const string hi="Hello";//True:初始化   
const int i;//Error:i is uninitialized const  
const string hi="Hello";//True:初始化
const int i;//Error:i is uninitialized const

5、const引用:const引用时执行const对象的引用

view plaincopy to clipboardprint?
const int ival=1024;   
const int &refival=ival;//OK:both reference and object are const   
int &refival2=ivale;//error:nonconst reference to a const object  
const int ival=1024;
const int &refival=ival;//OK:both reference and object are const
int &refival2=ivale;//error:nonconst reference to a const object

6、用class和struct关键字定义类的唯一差别在于默认访问级别:默认情况下struct的成员为public.而class成员为private.

第三章 标准库类型
除了基本的数据类型外,C++还定义了一个内容丰富的抽象数据类型标准库。其中最重要的标准库类型就是string和vector,他们分别定义了大小可变的字符串和集合。另外一种标准库类型bitset提供了一种抽象方法来操作位的集合。本章主要介绍标准库中的vector、string和bitset类型。

1、string类型对象的定义和初始化

view plaincopy to clipboardprint?
#include<string>   
using std::string;   
  
string s1;   
string s2(s1);   
string s3("value");   
string s4(n,'c');  
#include<string>
using std::string;

string s1;
string s2(s1);
string s3("value");
string s4(n,'c');

2、为了与C语言兼容,字符串字面值与标准库string类型不是同一种类型,编程时一定要注意区分。 当进行string对象和字符串字面值混合连接操作时,+操作符的左右操作符必须至少有一个是string类型的。

view plaincopy to clipboardprint?
string s1="hello";   
string s2="world";   
string s3=s1+","; //OK   
string s4="hello"+",";//Error   
string s5=s1+s2;//OK  
string s1="hello";
string s2="world";
string s3=s1+","; //OK
string s4="hello"+",";//Error
string s5=s1+s2;//OK


3、#include<cctype.h>对string对象中单个字符进行处理。

4、标准库vector类型

view plaincopy to clipboardprint?
#include<vector>   
using std:vector;   
  
vector<T> v1;   
vector<T> v2(v1);   
vector<T> v3(n,i);   
vector<T> v4(n);   
  
v.empty();//如果v为空,则返回true   
v.size();//返回v中元素的个数   
v.push_back(t);//在v的末尾增加一个值为t的元素  
#include<vector>
using std:vector;

vector<T> v1;
vector<T> v2(v1);
vector<T> v3(n,i);
vector<T> v4(n);

v.empty();//如果v为空,则返回true
v.size();//返回v中元素的个数
v.push_back(t);//在v的末尾增加一个值为t的元素

5、仅能对确知已存在的元素进行下标操作:

view plaincopy to clipboardprint?
vector<int> ivec;   
cout<<ivec[0];//Error:ivec has no elements   
  
vector<int> ivec2(10);   
cout<<ivec2[10];//Error:ivec has elements 0...9  
vector<int> ivec;
cout<<ivec[0];//Error:ivec has no elements

vector<int> ivec2(10);
cout<<ivec2[10];//Error:ivec has elements 0...9

6、除了使用下标来访问vector对象的元素外,标准库还提供了另一种访问元素的方法:使用迭代器,迭代器是一种检查容器内元素并遍历元素的数据类型。

view plaincopy to clipboardprint?
vector<int>::iterator iter;  
vector<int>::iterator iter;

7、begin和end操作:

view plaincopy to clipboardprint?
vector<int>::iterator iter=ivec.begin();//指向第一个元素   
vector<int>::iterator iter=ivec.end();//由end操作返回的迭代器指向vector的"末端元素的下一个"  
vector<int>::iterator iter=ivec.begin();//指向第一个元素
vector<int>::iterator iter=ivec.end();//由end操作返回的迭代器指向vector的"末端元素的下一个"

8、解引用操作符*与下标的区别

view plaincopy to clipboardprint?
for(vector<int>::size_type ix=0;ix!=ivec.size();++ix)   
    ivec[ix]=0;   
  
for(vector<int>::iterator iter=ivec.begin();iter!=ivec.end();++iter)   
    *iter=0;  
for(vector<int>::size_type ix=0;ix!=ivec.size();++ix)
    ivec[ix]=0;

for(vector<int>::iterator iter=ivec.begin();iter!=ivec.end();++iter)
    *iter=0;

9、每种容器类型还定义了一种名为const_iterator的类型,该类型只能用于读取容器内元素,但不能改变其值。使用const_iterator类型时,我们可以得到一个迭代器,它自身的值可以改变,但不能用来改变所指向的元素的值。

view plaincopy to clipboardprint?
for(vector<string>::const_iterator iter=text.begin();iter!=text.end();++iter)   
    cout<<*iter<<endl;//print each element in text   
  
for(vector<string>::const_iterator iter=text.begin();iter!=text.end();++iter)   
    *iter=" ";//Error:*iter is const  
for(vector<string>::const_iterator iter=text.begin();iter!=text.end();++iter)
    cout<<*iter<<endl;//print each element in text

for(vector<string>::const_iterator iter=text.begin();iter!=text.end();++iter)
    *iter=" ";//Error:*iter is const

10、不要把const_iterator对象与const的iterator对象混淆起来,声明一个const迭代器时,必须初始化迭代器。一旦被初始化后,就不能改变它的值。

view plaincopy to clipboardprint?
vector<int> nums(10);//nums is nonconst   
const vector<int>::iterator cit=nums.begin();   
*cit=1;//OK:cit can change its underlying element   
++cit;//Error:can't change the value of cit  
vector<int> nums(10);//nums is nonconst
const vector<int>::iterator cit=nums.begin();
*cit=1;//OK:cit can change its underlying element
++cit;//Error:can't change the value of cit

11、string对象和bitset对象之间是反向转化的:string对象的最右边字符用来初始化bitset对象的低阶位。当用string对象初始化bitset对象时,记住这一差别很重要。如果string对象的字符个数小于bitset类型的长度,则高阶位置为0.

view plaincopy to clipboardprint?
string strval("1100");   
bitset<32> bitvec(strval);//bitvec的位模式中第2和3的位置为1,其余位置为0  
string strval("1100");
bitset<32> bitvec(strval);//bitvec的位模式中第2和3的位置为1,其余位置为0

第四章 数组和指针
C++语言提供了两种类似于vector和迭代器类型的低级复合类型——数组和指针。现代C++程序应尽量使用vector和迭代器类型,而避免使用低级的数组和指针,设计良好的程序只有在强调速度时才在类实现的内部使用数组和指针。与vector类型相比,数组的显著缺陷在于:数组的长度是固定的,而且程序员无法知道一个给定数组的长度,数组没有获取其容量大小的size操作,也不提供push_back操作在其中自动添加元素。如果需要更改数组的长度,程序员只能创建一个更大的新数组,然后把原数组的所有元素复制到新数组空间中。

1、数组的定义和初始化:数组的维数必须用值大于等于1的常量表达式定义,此常量表达式只能包含整型字面值常量、枚举常量或者用常量表达式初始化的整型const对象。非const变量以及要到运行阶段才知道其值的const变量都不能用于定义数组的维数。

view plaincopy to clipboardprint?
const unsigned buf_size=512,max_files=20;   
int staff_size=27;   
const unsigned sz=get_size();   
  
char input_buffer[buf_size];//ok,const variable   
string fileTable[max_files+1];//ok,constant expression   
double salaries[staff_size];//error:non const variable   
int test_scores[get_size()];//error:要到运行时调用函数才知道值,non const expression   
int vals[sz];//error:size not konwn until run time  
const unsigned buf_size=512,max_files=20;
int staff_size=27;
const unsigned sz=get_size();

char input_buffer[buf_size];//ok,const variable
string fileTable[max_files+1];//ok,constant expression
double salaries[staff_size];//error:non const variable
int test_scores[get_size()];//error:要到运行时调用函数才知道值,non const expression
int vals[sz];//error:size not konwn until run time

2、不允许数组直接复制和赋值:与vector不同,一个数组不能用另外一个数组初始化,也不能将一个数组赋值给另一个数组。

view plaincopy to clipboardprint?
int ia[]={0,1,2};   
int ia2[](ia);//error:不能用另外一个数组初始化   
  
const unsigned array_size=3;   
int ia3[array_size];//ok,but elements are uninitialized   
ia3=ia;//error:不能将一个数组赋值给另外一个数组  
int ia[]={0,1,2};
int ia2[](ia);//error:不能用另外一个数组初始化

const unsigned array_size=3;
int ia3[array_size];//ok,but elements are uninitialized
ia3=ia;//error:不能将一个数组赋值给另外一个数组

3、数组的长度是固定的:与vector不同,数组不提供push_back或者其他的操作在数组中添加新元素,数组一经定义,就不允许再添加新的元素。

4、vector的遍历可使用下标或迭代器实现,同理,也可用下标或指针来遍历数组,指针式指向某种类型对象的符合数据类型,是用于数组的迭代器,指向数组中的一个元素,在指向数组元素的指针上使用解引用操作符*和自增操作符++,与在迭代器上的用法类似。

view plaincopy to clipboardprint?
string s("helloworld");   
string *sp=&s;//定义了一个指向string类型的指针sp  
string s("helloworld");
string *sp=&s;//定义了一个指向string类型的指针sp

5、理解指针声明语句时,请从右向左阅读

view plaincopy to clipboardprint?
string *pstring;//把pstring定义为一个指向string类型对象的指针变量   
  
double dp,*dp2;//该语句定义了一个double类型的dp对象以及一个指向double类型对象的指针dp2   
  
string* ps;//把ps定义为一个指向string类型对象的指针   
  
string* ps1,ps2;//ps1定义为指针,ps2并非指针,只是一个普通的string对象而已   
  
string* ps1,*ps2;//定义两个指针  
string *pstring;//把pstring定义为一个指向string类型对象的指针变量

double dp,*dp2;//该语句定义了一个double类型的dp对象以及一个指向double类型对象的指针dp2

string* ps;//把ps定义为一个指向string类型对象的指针

string* ps1,ps2;//ps1定义为指针,ps2并非指针,只是一个普通的string对象而已

string* ps1,*ps2;//定义两个指针

6、指针初始化和赋值操作的约束,对指针进行初始化或赋值只能使用以下四种类型的值:(1) 0值常量表达式(2) 类型匹配的对象的地址(3) 另一对象之后的下一地址(4) 同类型的另一个有效指针。把int型变量赋给指针是非法的。

view plaincopy to clipboardprint?
int ival;   
int zero=0;   
const int c_ival=0;   
int *pi=ival;//error:pi initialized from int value of ival   
pi=zero;//errro:pi assigned int value of zero   
pi=c_ival;//ok:c_ival is a const with compile time value of 0   
pi=0;//ok:directly initialize to literal constant 0  
int ival;
int zero=0;
const int c_ival=0;
int *pi=ival;//error:pi initialized from int value of ival
pi=zero;//errro:pi assigned int value of zero
pi=c_ival;//ok:c_ival is a const with compile time value of 0
pi=0;//ok:directly initialize to literal constant 0

7、void*指针:它可以保存任何类型对象的地址:void*表明该指针与一地址值相关,但不清楚存储在此地址上的对象的类型,void*指针只支持几种有限的操作:与另一个指针进行比较;向函数传递void*指针或从函数返回void*指针;给另一个void*指针赋值。不允许使用void*指针操作它所指向的对象。

view plaincopy to clipboardprint?
double obj=3.14;   
double *pd=&obj;   
void *pv=&obj;   
pv=pd;  
double obj=3.14;
double *pd=&obj;
void *pv=&obj;
pv=pd;

8、指针提供间接操作其所指对象的功能,与对迭代器进行解引用操作一样,对指针进行解引用可访问它所指的对象。

view plaincopy to clipboardprint?
string s("hello world");   
string *sp=&s; //sp holds the address of s   
cout<<*sp;   //print hello world  
string s("hello world");
string *sp=&s; //sp holds the address of s
cout<<*sp;   //print hello world

9、指针和引用的比较,虽然使用引用和指针都可间接的访问另一个值,但它们之间有两个重要的区别:

第一个区别在于引用总是指向某个对象,定义引用时没有初始化是错误的;第二个去背则是赋值行为的区别,给引用赋值修改的是该引用所关联的对象的值,而并不是引用与另一个对象关联。引用一经初始化,就始终指向同一个特定对象。

view plaincopy to clipboardprint?
//赋值结束后,pi所指向的ival对象值保持不变   
int ival=1024,ival2=2048;   
int *pi=&ival,*pi2=&ival2;   
pi=pi2;//pi now points to ival2   
  
//这个赋值操作修改了ri引用的值ival对象,而并非引用本身   
int &ri=ival,&ri2=ival2;   
ri=ri2; //assigns ival2 to ival  
//赋值结束后,pi所指向的ival对象值保持不变
int ival=1024,ival2=2048;
int *pi=&ival,*pi2=&ival2;
pi=pi2;//pi now points to ival2

//这个赋值操作修改了ri引用的值ival对象,而并非引用本身
int &ri=ival,&ri2=ival2;
ri=ri2; //assigns ival2 to ival


10、指向指针的指针:C++使用**操作符指派一个指针指向另一个指针,为了真正访问到ival对象,必须对ppi进行两次解引用。

view plaincopy to clipboardprint?
int ival=1024;   
int *pi=&ival;//pi points to an int    
int **ppi=π//指向指针的指针   
  
cout<<**ppi<<endl;//两次解引用取得ival的值  
int ival=1024;
int *pi=&ival;//pi points to an int 
int **ppi=π//指向指针的指针

cout<<**ppi<<endl;//两次解引用取得ival的值

11、指针和const限定符

(1) 指向const对象的指针:如下的cptr是一个指向double类型const对象的指针,const限定了cptr指针所指向的对象类型,而并非cptr本身。也就是说cptr本身并不是const,如果需要的话,允许给cptr重新赋值,使其指向另一个const对象,但不能通过cptr修改其所指对象的值。同时把const对象的地址赋给一个普通的、非const对象的指针也会导致编译时的错误,不能使用void*指针保存const对象的地址

view plaincopy to clipboardprint?
const double *cptr;//cptr may point to a double that is const   
  
const double pi=3.1415;   
double *ptr=&pi;//error:ptr is a plain point   
const double *cptr=&pi;//ok   
*cptr=42;//error:*cptr might be const   
  
const int universe=42;   
const void* cpv=&universe;//ok:cpv is const   
void *pv=&universe;//error:不能使用void*指针保存const对象的地址   
  
double dval=3.14;   
cptr=&dval;//允许把非const对象的地址赋给指向const对象的指针  
const double *cptr;//cptr may point to a double that is const

const double pi=3.1415;
double *ptr=&pi;//error:ptr is a plain point
const double *cptr=&pi;//ok
*cptr=42;//error:*cptr might be const

const int universe=42;
const void* cpv=&universe;//ok:cpv is const
void *pv=&universe;//error:不能使用void*指针保存const对象的地址

double dval=3.14;
cptr=&dval;//允许把非const对象的地址赋给指向const对象的指针

(2) const指针:本身的值不能修改,如下curErr是指向int型对象的const指针,const指针的值不能修改,这就意味着不能使curErr指向其他对象,任何企图给const指针赋值的行为,都会导致编译时的错误

view plaincopy to clipboardprint?
int errNumb=0;   
int *const curErr=&errNumb;//curErr为const指针   
  
curErr=curErr;//异常:不能修改const指针的值  
int errNumb=0;
int *const curErr=&errNumb;//curErr为const指针

curErr=curErr;//异常:不能修改const指针的值

(3) 指向const对象的const指针:既不能修改pi_ptr所指向对象的值,也不允许修改该指针的指向。

view plaincopy to clipboardprint?
const double pi=3.1415926;   
const double *const pi_ptr=pi;//  
const double pi=3.1415926;
const double *const pi_ptr=pi;//

12、指针和typedef,如下面代码所示,cstr变量是什么类型?

view plaincopy to clipboardprint?
typedef string *pstring;   
const pstring cstr;  
typedef string *pstring;
const pstring cstr;

一般说来cstr是const pstring类型的指针,那const pstring指针所表示的真实类型是什么?注意不是指向string类型的const对象(不能简单的把typedef当做文本扩展),而是指向string类型对象的const指针,因为const修饰的是pstring的类型。

13、C风格字符串:以空字符null结束的字符数组

view plaincopy to clipboardprint?
char cal1[]={'C','+','+'};//不是C风格字符串   
char cal2[]={'C','+','+','/0'};//C风格字符串   
char cal3[]="C++";//自动添加null,为C风格字符串  
char cal1[]={'C','+','+'};//不是C风格字符串
char cal2[]={'C','+','+','/0'};//C风格字符串
char cal3[]="C++";//自动添加null,为C风格字符串

14、C风格字符串的标准库函数,必须包含相应的C头文件#include<cstring>

view plaincopy to clipboardprint?
strlen(s);//返回s的长度,不包括字符串结束符null   
strcmp(s1,s2);//比较两个字符串s1和s2是否相同。   
strcat(s1,s2);//将字符串s2连接到s1后,并返回s1   
strcpy(s1,s2);//将s2复制给s1,并返回s1   
strncat(s1,s2,n);//将s2的前n个字符连接到s1后面,并返回s1   
strncpy(s1,s2,n);//将s2的前n个字符复制给s1,并返回s1  
strlen(s);//返回s的长度,不包括字符串结束符null
strcmp(s1,s2);//比较两个字符串s1和s2是否相同。
strcat(s1,s2);//将字符串s2连接到s1后,并返回s1
strcpy(s1,s2);//将s2复制给s1,并返回s1
strncat(s1,s2,n);//将s2的前n个字符连接到s1后面,并返回s1
strncpy(s1,s2,n);//将s2的前n个字符复制给s1,并返回s1

15、动态定义数组以及初始化数组:可以使用跟在数组长度后面的一对空圆括号对数组元素做值初始化。

view plaincopy to clipboardprint?
int *pia=new int[10];//分配了一个含有10个int型元素的数组   
int *pia2=new int[10]();//把数组元素都设置为0   
  
const int *pci_bad=new const int[100];//Error:uninitialized const array   
const int *pci_ok=new const int[100]();//OK:value-initialized const array  
int *pia=new int[10];//分配了一个含有10个int型元素的数组
int *pia2=new int[10]();//把数组元素都设置为0

const int *pci_bad=new const int[100];//Error:uninitialized const array
const int *pci_ok=new const int[100]();//OK:value-initialized const array

16、C语言使用一对标准库函数malloc和free在自由存储区分配存储空间,而C++语言则使用new和delete表达式实现相同的功能。注意动态空间的释放,在关键字delete和指针之间的空方括号对必不可少。它告诉编译器该指针指向的是自由存储区中的数组,而并非单个对象。

view plaincopy to clipboardprint?
delete [] pia;//该语句回收了pia所指的数组  
delete [] pia;//该语句回收了pia所指的数组

17、string类提供了一个名为c_str的成员函数,用于返回C风格字符串,即返回指向字符数组首地址的指针,该数组存放了与string对象相同的内容,并且以结束符null结束。

view plaincopy to clipboardprint?
string str("Hello World");   
char *str1=str;//Error   
char *str2=str.c_str();//OK  
string str("Hello World");
char *str1=str;//Error
char *str2=str.c_str();//OK

第五章 表达式
本章重点介绍C++语言定义的操作符,他们使用内置类型的操作数。

1、sizeof操作符:返回一个对象或类型名的长度,返回的类型为size_t,长度的单位是字节,具有以下三种语法形式:

view plaincopy to clipboardprint?
sizeof(type name);   
sizeof(expr);   
sizeof expr;  
sizeof(type name);
sizeof(expr);
sizeof expr;

2、强制转换:dynamic_cast(支持运行时识别指针或引用所指向的对象)、const_cast(将转换掉表达式的const性质)、static_cast(编译器隐式进行的任何数据类型都可以由它显式完成)、reinterpret_cast(通常为操作数的位模式提供较低层次的重新解释)

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/rocket5725/archive/2009/09/17/4563837.aspx

猜你喜欢

转载自blog.csdn.net/cbk861110/article/details/89683757