new 数据类型int *p=new int(10);int *func()
{
int *a=new int(10);
return a;
}
/*
int main()
{
int *p=func();
cout<<*p<<endl;
delete p; //利用delete释放堆区数据
......
}
*/
//堆区开辟数据
int main()
{
int*arr=new int[10];
for(int i=0;i<10;i++)
{
arr[i]=i+100;
}
for(int i=0;i<10;i++)
{
cout<<arr[i]<<endl;
}
delete[]arr; //释放数组delete后加[]
system("pause");
return 0;
}
作用:给变量起别名
语法:数据类型 &别名 = 原名
注意事项:1)引用必须初始化 int &c ; (错误) int &c=b ; (正确)
2)引用在初始化后,不可以改变
引用做函数参数
作用:函数传参时,可以利用引用的技术让形参修饰实参
优点:可以简化指针修改实参
示例:
//1.值传递,形参不会修饰实参
void myswap01(int a,int b)
{
int temp=a;
a=b;
b=temp;
}
//2.地址传递,形参会修饰实参
void myswap02(int *a,int*b)
{
int temp=*a; //解引用
*a=*b;
*b=temp;
}
//3. 引用传递,形参会修饰实参
void myswap03(int &a,int &b)
{
int temp=a;
a=b;
b=temp;
}
int main()
{
int a=10;
int b-20;
//myswap01(a,b);
myswap02(&a,&b);
myswap03(a,b);
return 0;
}
//返回局部变量引用
int & test01()
{
int a=10; //局部变量,存放在栈区
return a;
}
//返回静态变量引用
int & test02()
{
static int a=20; //静态变量,存放在全局区
return a;
}
int main()
{
//不能返回局部变量的引用
int &ref=test01();
cout<<"ref="<<ref<<endl; //第一次结果正确,是因为编译器做了保留
cout<<"ref="<<ref<<endl; //第二次结果错误,因为a的内存已经释放
cout<<"ref="<<ref<<endl; //之后都会错误
//如果函数做左值,必须返回引用
int &ref2=test02();
cout<<"ref2="<<ref2<<endl; /*此时结果会一直正确,因为返回的是静态变量引用,
存放在全局区,而不再栈区*/
cout<<"ref="<<ref<<endl;
test02()=1000; /*相当于使a=1000,ref2是a的别名。如果函数的返回值是引用,
这个函数调用可以作为左值*/
cout<<"ref2="<<ref2<<endl; //输出ref2=1000
}
//发现是引用,转换为int *const ref=&a;
void func(int &ref)
{
ref=100; //ref是引用,转换为*ref=100
}
int main()
{
int a=10;
//自动转换为int*const ref=&a; 指针常量是指针指向不可以改,也说明为什么引用不可以更改
int &ref=a;
ref=20; //内部发现ref是引用,自动帮我们转换为:*ref=20;
cout<<"a:"<<a<<endl;
cout<<"ref:"<<ref<<endl;
func(a);
return 0;
}
(C++推荐用引用技术,因为语法方便,引用本质是指针常量,但是所有的指针操作编译器都帮我们做了。)
// int &ref=10 ;(错误)引用本身需要一个合法的内存空间,因此这行错误
//加const就可以了,编译器优化代码,int temp=10;const int& ref=temp;
const int &ref =10;
//ref =100; (错误)加入const 后不可以修改变量
void showvalue (const int &v)
{
//v+=10; (错误)
cout<<v<<endl;
}
int main()
{
int a=10; //函数中利用常量引用防止误操作修改实参
showvalue(a);
}
函数默认参数
在C++中,函数的形参列表中的形参是可以有默认值的
(如果我们自己传入数据,就用自己的数据,如果没有,那么用默认值)
语法:返回值类型 函数名 (参数=默认值){ }
注意:1)如果某个位置参数有默认值,那么从这个位置往后,从左向右,必须都要有默认值。
2)如果函数声明有默认值,函数实现的时候就不能有默认参数,反之也一样。
函数占位参数
C++中函数的形参列表里可以有占位参数,用来做占位,调用函数时必须填补该位置。
语法:返回值类型 函数名 (数据类型){ }
void func(int a,int)
{
...
}
int main()
{
func(10,10); //占位参数必须填补
}
void func(int a,int=10) //占位参数也可以有默认参数
void func() (正确)
void func(int a) (正确)
void func(double a) (正确)
void func(int a,double b) (正确)
void func (double a,int b) (正确)
int func(double a,int b)) (错误)
函数重载注意事项(“坑”)
1)引用作为重载条件
2)函数重载碰到函数默认参数
//函数重载注意事项
//1. 引用作为重载条件
void func(int &a)
{
cout<<"func (int &a)调用"<<endl;
}
void func(const int &a)
{
cout<<"func (const int &a)调用"<<endl;
}
//2.函数重载碰到函数默认参数
void func2(int a,int b=10)
{
cout<<"func (int a,int b=10)调用"<<endl;
}
void func2(int a)
{
cout<<"func (int a)调用"<<endl;
}
int main()
{
int a=10;
func(a); //调用无const,该a可读可写
func(10); //调用有const,因为const int &a=10合法,而int &a=10不合法
func2(10); //错误,碰到默认参数,产生歧义,需要避免
func(10,20); //可以
... ...
}