指针形参
1.可以用指针作为函数的形参,这时相当于对实参指针做复制操作,形参初始化后,这两个指针指向相同的对象.如果在函数体内通过形参指针改变所指向对象的值,那么显然以后对实参指针解引用也会发现值已经改变了;如果只是改变形参指针的本身的值,也就是让它指向另一个对象,那个实参不会受到影响.
2.如果我们想使用指针形参,同时又想保护实参所指向对象的值,应该怎么办呢?我们可以将形参定义为指向 const 对象的指针,如:
void use_ptr(const int *p)
{...}
上例中,指针p是一个(自以为)指向const对象的指针,因此不管实参指针是不是"指向const对象的指针",形参指针都不能改变其所指对象的值.
3.规则是:可以让"指向const对象的指针"指向非const对象,但是不可以让"指向非const对象的指针"指向const对象.因此,对于形参为"指向非const对象的指针"的函数,不能用"指向const对象的指针"作为实参,因为这个实参已经自以为自己指向了一个const对象,形参一初始化的时候听到实参这么说,就初始化不下去了.
-----------------------------------
const形参
至于const形参.因为初始化的时候都是复制值,所以没有什么限制.
-----------------------------------
const引用
用一个例子说一下非const引用和const引用
int a=45;
int &b=a;//引用是别名,这里b是a的别名
b=46;
cout<<a<<endl; //print:46
double &c=a;//error:非const引用只能绑定与该引用相同类型的对象
const double &d=a;//ok:const引用可以绑定到不同但相关的类型或绑定到右值,但这里的d就不是a的别名,
//而只是一个将a转换为double型对象产生的副本的别名
d=47;//error:const引用是只读的
a=48;
cout<<b<<endl;//print:48
cout<<d<<endl;//print:46
const int e=49;
int &f=e;//error:非const引用不能绑定到const对象
const int &g=e;//ok:这样就靠谱了.
-----------------------------------
引用形参
更多的时候,我们会使用引用形参.我们或许需要在函数中修改实参的值,或者我们希望函数返回不只一个值,又或者复制实参花费的代价太大甚至无法复制.当然,在刚才所说的最后一种情况下,我们又不想修改实参,那么我们可以使用const引用,比如:
void fun(const string &str)
{...}
这就在fun()这个函数里,把引用进来的某个实参指定成了const string类型,就不能改变其值了,同时又不需要花费代价复制实参.
同上面一小节一样,非const引用形参只能与完全同类型的非const对象关联.显然,在确定不需要修改实参的情况下,我们应该将相应的形参定义为const引用,这样可以是函数使用更灵活且不会产生上面一小节上面那样的副作用.
------------------------------------
传递指向指针的引用
如果我们想在函数里直接改变实参指针的值呢?那么就要同时用到*和&,课本上的例子如下:
void ptrswap(int *&v1,int *&v2)
{...}
形参int *&v1应该这样理解:(int *)(&v1),从右至左,这是一个引用(&v1),这个引用指向的类型是 int型对象的指针(int *).
想想,压力,是显而易见的.