2 const 指针
int *const cur;
1 const指针的值不可改变
int err=4,num=8;
int *const cur=&err; (O)
cur=# (X)
2 const指针在定义时必须初始化
3 可以使用const指针修改它所指对象的值
*cur=0; (O)
3 指向const对象的const指针
const double pi=3.14;
const double *const pi_ptr=π
既不能改变指针所指向对象的值,也不可修改指针本身。
4 typedef 和指针
typedef string *pstring;
const pstring cstr;
问:cstr是什么类型
答:const 修饰的是pstring 的类型,而pstring 是一个指向string类型对象的指针
因此,cstr是一个指向string类型对象的const指针,即
string *const cstr;
而不是 const string * cstr;
5 const string str;与 string const str 都是一个意思。
6 使用数组初始化vector对象
必须指出第一个元素以及数组最后一个元素的下一个位置的地址
const size_t arr_size=6;
int int_arr[arr_size]={0,1,2,3,4,5};
vector<int> ivec(int_arr,int_arr+arr_size);
还可以并不完全都将原来数组内容全部包含。
7
7 指针与多维数组
int ia[3][4];
int (*ip)[4]=ia;//ip是一个指向含有4个元素的数组的指针
ip=&ia[2];//ip指向最后含有4个元素的一行了。
8 数组指针与指针数组
int *ip[4]; //指针数组,含有4个指针的数组,与普通数组的区别就是元素是地址(指针),而非数值
int (*ip)[4]; //数组指针,指向含有4个元素的数组的指针
9 typedef与多维数组指针
typedef int int_arr[4];
int_arr *ip=ia;
for(int_arr *p=ia;p!=ia+3;++p)
{
for(int *q=*p;q!=*p+4;++q)
{
cout<<*q<<endl;
}
}
10 创建 删除 动态数组
int *ptr=new int[10];
对于动态数组,只能初始化为元素类型的默认值,无法赋予其他值。
但是,字符串类型的就特殊一些
string *pstr=new string(10,'9');
推而广之到其他类型,都可以。但是必须是各个类型的指针做左值。
int i=new int(1024); (X)
删除很简单
delete[] ptr;
delete ptr;
而且,删除0值的指针是可以的
一旦删除指针指向的对象后,立即将指针赋值为0。 p=null是好习惯。
11 const对象的分配与回首
const int *pci_err=new const int[10]; (X)
const int *pci_ok=new const int[10](); (O)
因为对于const变量是需要进行初始化的
但是,
const string *cstr=new const string[100]; (O)
这是因为使用了string类的默认构造函数
删除时:
delete [] pci_ok;
12 空数组
char ma[0]; (X)
char *mama=new char[0]; (O)
13 异常处理
1 throw 错误检查部分使用它来说明遇到了不可处理的错误,引发了异常条件。停止余下程序的执行,并将控制转移给处理这种错误的处理代码。
2 try-catch 后面跟多个catch,
try{
xxxxxxxxxxx
}catch(异常说明符)
{
xxxxxxxxxxx
}
int i=0;
while(i!=10)
{
try{
int a,b;
cin>>a>>b;
if(a!=b)
throw runtime_error("Data must refer to same ISBN");
cout<<"a!=b";
}catch(runtime_error err){
cout<<err.what()<<"/nTry again? Enter y or n"<<endl;
char c;
cin>>c;
if(cin&&c=='n')
break;
}
i++;
}
在try中,当遇到throw后开始转入相应的catch语句.
14 非引用形参
1 普通形参:复制实参初始化。函数不会访问调用所传递的实参本身,不会改变实参的值。
2 指针形参:被复制的指针只是影响对指针的赋值。若函数形参是非const类型的指针,则函数可通过指针实现赋值,修改指针所指向对象的值。
void reset(int *ip)
{
//改变了实参指针所指向的值
*ip=0;
//没有改变实参
ip=0;
}
如果连实参指针所指的值都不能变,就用 const int *ip
对于
void fun1(int *ip)
void fun2(const int *ip)
可以用int *,也可以用const int *来调用 fun2;
但是只能int *调用fun1.
3 const形参
1 如果憾事使用非引用非const形参,己可以传递const实参,也可以传递非const实参。
2 如果形参定义为非引用的const类型。则在函数中,不可以改变实参的局部副本。而实参可以是const也可以是非const.
15 引用形参
1 引用形参直接绑定到实参,而非形参的副本。
2 利用引用返回额外的值。因为引用实参在函数中会变化,因此在函数外可以获取其至。
3 利用const避免复制 const string &str
const 引用就是避免复制实参。而且实参在函数中不会被改变。这样就避免了引用会改变实参的特性。
4 函数具有普通的非const引用形参,则不能通过const对象进行调用。这样会造成形参可变,而实参不可变。非const引用参数只能与完全同类型的非const对象关联。
5 应该将不需要修改的引用形参定义为const引用。对于非const引用,既不能用const对象初始化,不能用字面值活右值来初始化。
16 传递指向指针的引用
int *&val; //val是一个引用,与指向int型对象的指针相关联。是指针的别名。
17 数组形参的定义
void fun1(int *);
void fun2(int []);
void fun3(int [10]);
1 不修改实参指针的值,但是,函数却可以通过该指针来改变它所指向的数组元素的值。
2 不想修改数组形参的元素,可以定以为 void fun(const int*){};
18通过引用传递数组
1 形参是数组的引用,编译器不会将数组实参转化为指针,而是传递数组的引用本身。会检查数组实参与形参的大小。
void print(int (&arr)[10]){xxxx}
int k[10]={xxx};
print(k);//这是唯一的正确初始化方法
int &arr[10]; //arr是一个引用数组
int (&arr)[10] //arr是数组的引用
19 多维数组的传递
1 void print(int (*matrix)[10]);//matrix为指向含有10个int类型元素的数组的指针
2 编译器忽略第一维的长度。不要将起包含进来。
void print(int matrix[][10]); //等价
20 确保函数的操作不超出数组实参的边界
1 在数组本身防止一个标记检测数组的结束。 字符串以'/'结尾
2 传递给数组第一个和最后一个元素的下一个位置的指针。如同用数组初始化vector一样
3 将第二个形参定义为数组的大小。 void print(const int a[],size_t size);
21 返回引用
1 const string &func(const string &str)
{xxxxxxxxxx}
返回的是对象本身。
2 不要返回局部对象的引用
当函数执行完毕时,将释放分配给局部对象的存储空间。对局部对象的引用就会指向不确定的内存。
const string &map(const string &s)
{
string res=s;
return res; //disaster
3 给函数返回值赋值
char &get_val(string &str,size_t ix);
{
return str[ix];
}
string s("a value");
get_val(s,0)='A';//将A付给第一个字符。
//get_val(s,0)是一个引用,引用string类型s的第一个字符a
如果不想引用返回值被修改,可声明为 const char &get_val(xxx)
4 不要返回指向局部对象的指针。