在C++中,引用是变量的别名,所有对引用的修改都会改变被引用的变量的值,可以将引用当成隐式指针,但是这个指针没有取变量的地址。
使用引用的好处:
1)效率:复制较大的对象或者结构体需要一段时间,按引用传递只是把指向对象或者结构体的指针传递给函数
2)正确性:并非所有的对象都支持按值传递,及时允许按值传递的对象也许不会支持deepcopying.
下面写一些代码说明:
#include"stdafx.h"
#include<iostream>
usingnamespacestd;
/*
classTest
{
private:
int&y;
public:
Test(intyy):y(yy){}
~Test(){}
};
*/
voidswap(int&x,int&y)
{
inttemp= x;
x= y;
y= temp;
}
int_tmain(intargc,_TCHAR*argv[])
{
/*
intx = 5;
int&y = x;
constint &z = 6; //如果不添加const 则会出错(因为文本是不会改变的,相当于已经初始化的)
cout<<y<<" "<<z<<endl;
Testt(3);
// 创建引用时必须初始化。通常会在声明引用的时候对其初始化
// 但是对于包含类而言,需要在构造函数初始化器中初始化引用数据成员(如上所示)
int*pInt;
int*&pRef = pInt;
pRef= new int;
*pInt= 4;
cout<<*pInt<<" "<<pRef<<endl;
//注意第二个输出语句pRef仍然是一个地址pRef== pInt
*/
//将指针转换为引用(使用swap函数为例)
inta= 3;
intb= 4;
int*pA= &a;
int*pB= &b;
cout<<*pA<<" "<<*pB<<endl;
swap(*pA,*pB); //将指针传递过去
//swap(a,b);
cout<<*pA<<" "<<*pB<<endl;
getchar();
return0;
}
何时使用指针,何时使用引用:
在C++中,几乎所用能够使用引用的地方都可以使用指针得到解决.
但是引用比指针安全,对于我们平常的程序,大多数情况下,还是使用引用为好。如果存在申请内存,释放程序内存的情况,则使用指针,否则使用引用。(还是看大家个人喜好)
2.C++值const(直接代码显示)
//const指针
constint*pCi; //为了防止所指的值被修改和intconst* pCi等价(pCi是一个指针指向constint)
int*constpIc; //为了防止pIc本身被修改(pIc是一个const指针,指向int)
constint*constpCic; //防止两者都被修改(pIc是一个const指针,指向constint)
//const引用
intx=9;
constint&y= x;
/*
保证方法不改变成员的值
函数方法可以标记为const
例如
intgetX() const{return x;}
*/
3.C++ static
/*
classTest
{
public: //方便访问使用public
staticint n;
};
intTest::n = 10; //为static变量进行赋值
intmain()
{
cout<<Test::n<<endl; //对static变量的使用可以看出他不是类对象的一部分(函数也是一样)
return0;
}*/
intprint()
{
staticint num;
num++;
returnnum;
}
intmain()
{
for(inti=0; i<10; ++i)
{
cout<<print()<<" ";
}
return0;
}
4.C++类型转换
1)const_cast 解除const修饰
#include"stdafx.h"
#include<iostream>
usingnamespacestd;
voidchange(char*str)
{
cout<<str<<endl;
}
voidfunc(constchar*str)
{
change(const_cast<char*>(str));
}
int_tmain(intargc,_TCHAR*argv[])
{
constchar*str="Hello";
func(str);
getchar();
return0;
}
2)dynamic_cat
#include"stdafx.h"
#include<iostream>
usingnamespacestd;
classCBasic
{
public:
virtualinttest(){return0;} //一定要是virtual
};
classCDerived: publicCBasic
{
public:
virtualinttest(){return1;}
};
intmain()
{
CBasic cBasic;
CDerived cDerived;
CBasic* pB1= newCBasic;
CBasic* pB2= newCDerived;
//dynamiccast failed, so pD1 is null.
CDerived* pD1= dynamic_cast<CDerived* > (pB1);
//dynamiccast succeeded, so pD2 points to CDerived object
CDerived* pD2= dynamic_cast<CDerived* > (pB2);
//dynamcicast failed, so throw an exception.
CDerived& rD1= dynamic_cast<CDerived&> (*pB1);
//dynamiccast succeeded, so rD2 references to CDerived object.
CDerived& rD2= dynamic_cast<CDerived&> (*pB2);
return0;
}
/*
以上是摘自网上的一个实例
dynamic_cast为继承层次内类型转换提供运行时检测,可以用来转换指针和引用
类至少有一个虚表
*/
3)static_cast
static_cast运行时不执行运行期间类型检测,此时有可能会导致运行时错误,例如:
CBaseb = new CBase();
CDrived*d = static_cast<CDerived*>(b);
(内存开销超出了对象的边界)
4)reinterpret_cast
Reinterpret_cast比static_cast的功能更加强大,安全性则更差,可以将某种类型指针任意转换。当然运行时也不会执行类型检测。