int a = 1;
int& b = a;
int& c = a;
int& d = a;
cout<<&a<<" "<<&b<<" "<<&c<<" "<<&d<<endl;
cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl;
![](//img-blog.csdn.net/20180316145004375)
引用的特点:①一个变量可以有多个别名;
②引用必须初始化;
③引用只能在初始化时引用一次(否则就是简单的把原来引用的变量进行了赋值);
还有一种引用的方式:使用关键字:const(即可以引用常量,也可以引用变量,但是不能通过这个变量来修改值)
int a = 1;
int& b = a;
const int& c = a;
const int& d = 10;
const int a = 10;
int& b = a; //错误的,是权限的放大。
int d = 10;
double e = d; //隐式类型的转换。
int a = 1;
int& b = a;
double& c = a; //这里会报错----->隐式类型转换,中间有临时变量,临时变量具有常性。
const double& d = a; //这个确实正确的
const int a = 1;int& b = a; 错误
但是这样就是正确的:
int a = 1;
const int& b = a;
引用的应用
int Big(int a,int b)
{
if(a > b)
{
return a;
}
return b;
}
int main()
{
const int& r = Big(3,5);
cout<<r<<endl;
system("pause");
return 0;
}
但是如果我们在主函数中接收返回值时去掉const,程序就会报错。原因和上面的原因相同,在返回时会生成一个临时变量(在寄存器中),而临时变量具有常性。
int& Big(int a,int b)
{
if(a > b)
{
return a;
}
return b;
}
int main()
{
int& r = Big(3,5);
system("pause");
return 0;
}
int& r = Big(3,5); //结果是5
Big(10,5); //结果是10;
用引用做参数:
void Swap(int& a,int& b)
{
int tmp = a;
a = b;
b = tmp;
}
int main()
{
int a = 10;
int b = 20;
Swap(a,b);
return 0;
}
2.如果是很大的,在传值时就是拷贝,就会浪费空间和造成效率低。所以可以传引用,但是传引用时,在函数体内改变了,就会导致在函数体外也会被改变,因此可以在引用的参数前加const.
sizeof(引用)------>是变量的大小。
sizeof(指针)------->是4(32位系统)。
指针(++/--)------->加/减类型的大小。
引用(++/--)-------->加/减1.
class Student
{
public:
void Show()
{
cout<<_name<<" is "<<age<<endl;
}
public:
char* _name;
int age;
};
int main()
{
Student A;
A._name = "huhu";
A.age = 6;
A.Show ();
system("pause");
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/a1d06cc8502ee9015e0717d78a0a0b62.png)
内联函数(inline)
以inline修饰的函数叫做内联函数,C++编译时会在调用内联函数的地方进行展开,没有函数压栈的开销,提高了程序的运行效率。
内联函数的调用过程:在调用一个内联函数时,编译器首先会检查调用是否正确(如:进行类型安全检查)。如果正确,内联函数的代码会直接替换函数调用,所以就省去了函数调用栈帧的开销。这里与预处理有显著的区别,因为预处理器不能进行类型安全的检查。
特点:
- inline函数是一种以空间换时间的做法,省去函数在调用过程中栈帧的开销。
- inline必须与定义放在一起,才能成为内联函数。仅与声明放在一起是不起任何作用的。
- 定义在类内成员函数默认为内联函数。
- inline对于编译器而言只是一种建议,编译器会自动优化。当inline函数内部有循环/递归等,编译器优化时会忽略掉内联。
缺点:内联函数是以代码膨胀为代价的,仅仅省去了函数栈帧的开销。如果执行函数体内代码的时间,相较于函数调用的开销大,那么效率反而会降低。另一方面,每一处内联函数调用都会复制代码,将程序的代码量增大,消耗更多的内存空间。
下面我们写一个实例:
class AA
{
public:
void Show() //定义在类内的成员函数默认为内联函数
{
cout<<"Show()"<<endl;
}
void Display();
private:
int _a;
int _b;
};
inline void AA::Display() //inline关键字要与定义放在一起
{
cout<<_a<<endl;
cout<<_b<<endl;
}
友元函数
关键字:friend;
特点:在C++中,友元函数允许在类外访问类内的任何成员,就像成员函数一样。
强调:
- 友元函数不是类的成员函数;
- 友元函数可以通过类的对象访问任何成员,包括私有和保护。
class Date
{
public:
Date(int year,int month,int day)
:_year(year)
,_month(month)
,_day(day)
{}
friend void Display(const Date& d);
friend ostream& operator<<(ostream& out,const Date& d); //重载<<符号
friend istream& operator>>(istream& in,Date& d); // 重载<<符号
private:
int _year;
int _month;
int _day;
};
void Display(const Date& d)
{
cout<<d._year<<"-"<<d._month<<"-"<<d._day<<endl;
}
ostream& operator<<(ostream& out,const Date& d)
{
out<<"年:"<<d._year <<endl;
out<<"月:"<<d._month <<endl;
out<<"日:"<<d._day <<endl;
return out;
}
istream& operator>>(istream& in,Date& d)
{
in>>d._year ;
in>>d._month ;
in>>d._day ;
return in;
}
注意:在重载<<和>>符号时,就必须用到友元函数了,因为在成员函数中会有this指针,而this指针总是第一个参数,而<<和>>符号需要两个参数,而当是<<符号时,为了提高代码的可读性,就要把类的对象放在右边,但是this指针却是第一个参数(会出现在左边)。这样就不符合我们的要求了。所以在这儿可以用友元函数来实现输入输出运算符的重载。
注意:友元函数会破坏代码的封装性,所以,在很多场合下并不推荐使用友元函数。
static修饰的类的静态成员
特点:在类里面,用static修饰的成员,成为类的静态成员。
类的静态成员,被类的所有对象共享。
class Date
{
public:
Date(int year,int month,int day)
:_year(year)
,_month(month)
,_day(day)
{
++_count;
}
static void GetCount()
{
//在static函数内部,不可以调用非static成员,因为没有this指针,无法进行访问
cout<<Date::_count <<endl; //因为用static修饰的类的成员函数,没有this指针,所以只能通过类来访问
}
private:
int _year;
int _month;
int _day;
static int _count;
};
int Date::_count = 0;
敲黑板划重点啦:在类的静态成员函数中不可以访问非静态成员函数。在静态成员函数中没有this指针。
而在类的非静态成员函数中可以访问类的静态成员函数。