c++prime重学(一)基于第四版

数组:

1、如果没有显示提供元素初值,则数组回想普通变量一样初始化:

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

(2)在函数体内定义的内置数组,其元素无初始化。
(3)不管数组在哪里定义,如果其元素为类类型,则自动调用该类的默认构造函数进行初始化;如果该类

没有默认构造函数,则必须为该数组的元素提供显示初始化。

2、现代c++程序采用vector类型和迭代器取代一般的数组、采用string类型取代c风格字符串。

指针:

1、c++提供了一种特殊的指针类型void*,它可以保存任何类型对象的地址,void*表明该指针与一地址值相关,

但不清楚存储在此地址上的对象的类型。

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

(1)引用总是指向某个对象:定义引用时没有初始化是错误的;

(2)给引用赋值修改的是该引用所关联的对象的值,而并不是使引用与另一个对象关联。

引用一经初始化,就始终指向同一个特定对象(这就是为什么引用必须在定义是初始化的原因)

3、c++语言强制要求指向const对象的指针也必须具有const特性:const double *cpstr;

cptr本身并不是const,在定义时不需要对它进行初始化,如果需要的话允许给cptr重新赋值,使其指向另一个

const对象,但不能通过cptr修改其所指对象的值。把指向const对象的指针理解为“自以为指向const的指针”。

4、int *const curErr=&errNumb;读作"curErr是指向int 型对象的const指针",const指针的值不能修改,即不能

使curErr指向其他对象。

5、指向const对象的const指针:const double *const pi_ptr=π既不能修改pi_ptr所指向对象的值,也不允许

修改该指针的指向;读作”pi_ptr首先是一个const指针,指向double雷翔的const对象“

6、创建动态数组:每一个程序在执行时都占用一块可用的内存空间,用于存放动态分配的对象,此内存空间称为

程序的自由存储区或堆。

动态分配数组时,只需指定类型和数组长度,不必为数组对象命名,new表达式返回指向新分配数组的第一个元素的

指针:int *pia=new int[10];

释放:delete [] pia;该语句回收了pia所指向的数组。在关键字delete和指针之间的空方括号对是必不可少的:它告诉

编译器该指针指向的是自由存储区中的数组,而并非单个对象。
7、无法使用string对象初始化字符指针:

例:

string st("Hello world");

char *str=st;  //这样的赋值是错误的

char *str=st.c_str();  //这样的赋值是正确的(不完全正确)

c_str函数返回c风格字符串,其字面意思是:返回c风格字符串的表示方法,即返回指向字符数组首地址的指针,该数组

存放了与string对象相同的内容,并以结束符NULL借宿。

因为c_str返回的指针指向const char类型的数组,所以(char *str=st.c_str(); )初始化失败,这样做事为了避免修改该

数组。正确的初始化应为:const char *str=st.c_str();

8、数组指针和指针数组:优先级:()>[]>*

int *ip[4]:指针数组:存放指针的数组,即有4个元素,每个元素存放指针。p[0]、p[1]、p[2]...p[n-1],它们分别是指针变量可以用来存放变量地址

将二位数组赋给指针数组

int *p[3];
int a[3][4];
for(i=0;i<3;i++)
p[i]=a[i];

int (*ip)[4]:数组指针(也称行指针),指向数组的指针,即(ip+0)指向第0行(每行有四个元素),(ip+1)指向跨越第0行(四个元素),指向第一行。

首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是4,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。

如要将二维数组赋给一指针,应这样赋值:
int a[3][4];
int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
 p=a;        //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
 p++;       //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]

数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。

用typedef简化指向多维数组的指针

int ia[3][4];

typedef int int_array[4];

int_array *ip=ia;

for(int_array *p=ia;p!=ia+3;++p)

{

for(int *q=*p;q!=*p+4;++q)

{

cout<<*q<<endl;

}
}

//动态创建二位数组

const int column=4;
    const int row=6;
    int **arr=new int *[row];
    for(int i=0;i<row;++i)
        arr[i]=new int[column]();


    for(int i=0;i<row;++i)
        delete [] arr[i];
    delete [] arr;

9、位与操作(&)需要两个整型操作数,在每个位的位置,如果两个操作数对应的位都为1,

则操作结果中该位为1,否则为0。

位异或操作符(^)也需要两个整型操作数。在每个位的位置,如果两个操作数对应的位只有

一个(不是两个)为1,则操作结果中该位为1,否则为0。

位或操作符(|)需要两个整型操作数,如果两个操作数对应的位有一个或者两个都为1,则操作

结果为1.

10、 int i=0,j;
j=++i;
cout<<"j="<<j<<"i="<<i<<endl;
j=i++;
cout<<"j="<<j<<"i="<<i<<endl;

输出j=1,i=1;//先自增再赋值

j=1,i=2;//先赋值,再自增

vector<int>::iterator iter=ivec.begin();

*iter++:等效于*(iter++),子表达式iter++使iter加1,然后返回iter原值的副本作为该表达式

的结果。因此,解引用*的操作数是iter未加1前的副本。

11、sizeof操作符

(1)对char类型或值为char类型的表达式做sizeof操作保证得1。

(2)对引用类型做sizeof操作将返回存放此引用类型对象所需的内存空间大小。

(3)对指针做sizeof操作将返回指针所需的内存大小;注意,如果要获取该指针所指向对象的大小,则必须对该指针进行解引用。

(4)对数组做sizeof操作等效于将对其元素类型做sizeof操作的结果乘上数组元素的个数。因为sizeof返回整个数组在内存中的存储长度,所以用sizeof数组的结果除以sizeof其元素类型的结果,即可求出数组元素的个数。

12、显示转换(强制类型转换):static_cast  dynamic_cast  const_cast  reinterpret_cast

(1)dynamic_cast支持运行时识别指针或引用所指向的对象。

(2)const_cast  将转换掉表达式的const性质。

例:const char *pc_str;

char *pc=const_cast<char *>(pc_str);

(3)static_cast 编译器隐式执行的任何类型转换都可以游static_cast显示完成

double d=97.0;

char ch=static_cast<char>(d);

(4)reinterpret_cast reinterpret_cast 通常为操作数的位模式提供较低层次的重新解释

13、使用预处理器进行调试:程序所包含的调试代码尽在开发过程中执行。当应用程序已经完成,并且准备提交时,就会将调试代码关闭。可以使用NDEBUF预处理变量实现有条件的调试代码:

int main()

{

#ifndef NDEBUG

cerr<<"starting main"<<endl;

#endif;

}

14、int *func(){}  //该函数返回一个int型指针,该指针可以指向数组中的一个元素

15、如有下列函数

string::size_type find_char(string &s,char c)

{

string::size_type i=0; 

while(i!=s.size() && s[i]!=c)

i++;

return i;

}

当调用时:find_char("HELLO WORLD",'o');会出现编译错误。

总结:当不修改函数的实参时,应该把形参定义为const对象

string::size_type find_char(const string &s,const char c)

16、数组形参的定义

void print(int *);     void print(int []);     void print(int [10]); 是等价的,都是传递数组的首地址

17、inline函数避免函数调用的开销

例如:普通函数:const string &shorterString(const string &s1,const string &s2)

{

return s1.size()<s2.size()?s1:s2;

}

缺点:电泳函数比求解等价表达式要慢得多:调用前要先保存寄存器,并在返回时恢复;复制实参;程序还必须转向一个新位置执行

内联函数:

inline  const string &shorterString(const string &s1,const string &s2)

{

return s1.size()<s2.size()?s1:s2;

}

调用:cout<<shorterSting(s1,s2)<<endl;

在编译时将扩展为:cout<<(si.size()<s2.size() ? s1:s2)<<endl;

从而消除了把shorterString写成函数的额外执行开销。

注意:一般来说,内联机制适用于优化小的、只有几行的而且经常被调用的函数。大多数的编译器都不支持递归函数的内联。一个

1200喊的函数也不太可能在调用点内联展开。

18、this指针的引入

在调用成员函数时,形参this初始化为调用函数的对象的地址。

bool same_isbn(const Sales_item &rhs) 

{return isbn == rhs.isbn}

编译器重写:Sales_item::same_isbn(&total,trans);



19、bool same_isbn(const Sales_item &rhs)const 

{return isbn == rhs.isbn}

跟在Sales_item成员函数声明的形参表后面的const所引起的作用:const改变了隐含的this形参的类型。

编译器重写:Sales_item::same_isbn(const Sales_item *const this,const Sales_item &rhs)cosnt 。

使用const的函数称为常量成员函数。由于this是指向const对象的指针,const成员函数不能修改调用该函数的对象。




















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值