1.2引用

C++的引用,水很深

左值就是可以放在赋值号左边赋值的,必须要在内存有实体

右值就是可以放在赋值号右边取出值赋给其他变量的值,可以在内存,也可以在CPU

引用说明为对象建立引用名,即别名

引用在定义初始化时与对象名绑定,程序中不能对引用重定义

一个对象的别名,从使用方式和效果上,与使用对象名一致

定义形式:类型&引用名=对象名;

//引用可以改变指针的指向

//引用可以改变指针指向的值

 1 #include <iostream>
 2 using namespace std;
 3 
 4 void main()
 5 {
 6     int num1(5);
 7     int num2(10);
 8 
 9     int *pnum(&num1);
10 
11     int * & rpnum = pnum;//引用可以改变指针的指向
12 
13     *rpnum = 100;//引用可以改变指针指向的值
14 
15     rpnum = &num2;
16 
17     std::cout << *pnum << std::endl;//10
18 
19     system("pause");
20 }

//引用右值,一般用于企业开发,内存优化

//用于对象拷贝

 1 #include <iostream>
 2 using namespace std;
 3 
 4 void main()
 5 {
 6     int num1(5);
 7     int num2(10);
 8 
 9     int * && rpnum = &num1;//引用右值,一般用于企业开发,内存优化
10 
11     int *p = rpnum;//用于对象拷贝
12 
13     system("pause");
14 }

//指针与引用

int a;

int * pa;

int & ra=a;

pa=&a;

改变外部变量,需要地址或者引用

左值引用是用指针实现的

返回引用的函数

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int & get()
 5 {
 6     int a = 10;//a在栈上
 7     int & ra = a;
 8 
 9     std::cout << "&a=" << &a << std::endl;
10 
11     return ra;
12 }
13 
14 void main()
15 {
16     int & ra = get();
17 
18     std::cout << ra << std::endl;
19 
20     std::cout << "ABCD" << std::endl;
21 
22     std::cout << ra << std::endl;
23     
24     system("pause");
25 }

&左值引用

&&右值引用

 1 #include <iostream>
 2 using namespace std;
 3 
 4 void main()
 5 {
 6     int a = 10;
 7 
 8     int & ra = a;//&左值引用
 9 
10     int * && pa = &a;//&&右值引用
11 
12     //int * & & pa1 = &a;//右值引用,不能分开写
13     
14     system("pause");
15 }

面试,函数指针

int(*z(int x, int(*y)(int)))(int);

 1 #include <iostream>
 2 using namespace std;
 3 
 4 void main()
 5 {
 6     int(*z(int x, int(*y)(int)))(int);
 7 
 8     //第一步,可以看成
 9     int(*T)(int);
10 
11     //z(int x, int(*y)(int))
12     //z是一个函数,参数是一个整型变量和一个函数指针,返回值也是函数指针
13 
14     int(*y)(int);
15     //参数也有一个函数指针
16     
17     system("pause");
18 }

函数指针数组

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int jia(int a, int b)//定义一个函数+
 5 {
 6     return a + b;
 7 }
 8 
 9 int jian(int a, int b)//定义一个函数-
10 {
11     return a - b;
12 }
13 
14 void main()
15 {
16     int a = 10;
17     int b = 2;
18 
19     int(*p[2])(int, int) = { jia,jian };//定义一个函数指针数组,并初始化
20 
21     std::cout << p[0](a, b) << " " << p[1](a, b) << std::endl;//12 8
22 }

参数是函数指针的引用,返回一个函数指针的引用

int(*& z(int x, int(*& y)(int)))(int);

int a[10] = { 1,2,3,4,5,6,7,8,9,10 };

int(&ra)[10](a);//引用一个一维数组

 1 #include <iostream>
 2 using namespace std;
 3 
 4 void main()
 5 {
 6     int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
 7 
 8     //引用就是给变量有一个别名,同一个地址
 9 
10     int(&ra)[10](a);//引用一个一维数组
11 
12     for (auto data : ra)//C++11遍历一维数组新方法
13     {
14         std::cout << data << std::endl;
15     }
16 
17     std::cout << a << " " << ra << std::endl;
18 
19     std::cout << &a << " " << &ra << std::endl;
20     
21     system("pause");
22 }

int a[2][5] = { 1,2,3,4,5,6,7,8,9,10 };

int(&ra)[2][5](a);//引用一个二维数组

 1 #include <iostream>
 2 using namespace std;
 3 
 4 void main()
 5 {
 6     int a[2][5] = { 1,2,3,4,5,6,7,8,9,10 };
 7 
 8     int(&ra)[2][5](a);//引用一个二维数组
 9 
10     system("pause");
11 }

//创建一个函数指针,并初始化

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int jia(int a, int b)
 5 {
 6     return a + b;
 7 }
 8 
 9 void main()
10 {
11     int(*p)(int a, int b)(jia);//创建一个函数指针,并初始化
12 
13     std::cout << p(1, 2) << std::endl;//调用函数指针
14 
15     system("pause");
16 }

//引用一个函数指针

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int jia(int a, int b)
 5 {
 6     return a + b;
 7 }
 8 
 9 int jian(int a, int b)
10 {
11     return a - b;
12 }
13 
14 void main()
15 {
16     int(*p)(int a, int b)(jia);//创建一个函数指针,并初始化
17 
18     int(*& rp)(int a, int b)(p);//引用一个函数指针
19 
20     std::cout << rp(1, 2) << std::endl;
21 
22     rp = jian;//引用重新赋值
23 
24     std::cout << rp(1, 2) << std::endl;
25     
26     system("pause");
27 }

//改变一个函数指针的指向,需要一个指向函数指针的指针,或者这个函数指针的引用

void change(int(*& rp)(int, int))//参数值是函数指针的引用,无返回值

{

rp = jian;

}

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int jia(int a, int b)
 5 {
 6     return a + b;
 7 }
 8 
 9 int jian(int a, int b)
10 {
11     return a - b;
12 }
13 
14 //改变一个函数指针的指向,需要一个指向函数指针的指针,或者这个函数指针的引用
15 
16 void change(int(*& rp)(int, int))//参数值是函数指针的引用,无返回值
17 {
18     rp = jian;
19 }
20 
21 void main()
22 {
23     int(*p)(int a, int b)(jia);//创建一个函数指针,并初始化
24 
25     change(p);//通过函数改变一个函数指针的指向
26     
27     system("pause");
28 }

//升级版,比旧版更好,有返回值,可以监测是否成功改变
int(*& change(int(*& rp)(int, int)))(int, int)//参数值是函数指针的引用,返回一个函数指针的引用
{
rp = jian;
return rp;
}

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int jia(int a, int b)
 5 {
 6     return a + b;
 7 }
 8 
 9 int jian(int a, int b)
10 {
11     return a - b;
12 }
13 
14 //旧版
15 //void change(int(*& rp)(int, int))//参数值是引用一个函数指针,无返回值
16 
17 //第一步,引用函数指针
18 //int(*& T)(int,int)
19 
20 //第二步,中间补上
21 //升级版,比旧版更好,有返回值,可以监测是否成功改变
22 int(*& change(int(*& rp)(int, int)))(int, int)//参数值是函数指针的引用,返回一个函数指针的引用
23 {
24     rp = jian;
25     return rp;
26 }
27 
28 void main()
29 {
30     int(*p)(int a, int b)(jia);//创建一个函数指针,并初始化
31 
32     std::cout << p(1, 2) << std::endl;
33 
34     p = change(p);//参数是函数指针的引用,返回一个函数指针的引用
35 
36     std::cout << p(1, 2) << std::endl;
37     
38     system("pause");
39 }

//error C2234: “p”: 引用数组是非法的

 1 #include <iostream>
 2 using namespace std;
 3 
 4 void main()
 5 {
 6     int a = 1, b = 2, c = 3;
 7 
 8     int &p[4] = { &a,&b,&c };//error C2234: “p”: 引用数组是非法的
 9         
10     system("pause");
11 }

//引用数组是非法的,可以用指针数组

 1 #include <iostream>
 2 using namespace std;
 3 
 4 void main()
 5 {
 6     int a = 1, b = 2, c = 3;
 7 
 8     int *p[4] = { &a,&b,&c };//引用数组是非法的,可以用指针数组
 9         
10     system("pause");
11 }

//函数在代码区,无论一个类或结构体有多少个对象,它们的函数都是共有的

//代码区的函数不计入sizeof

 1 #include <iostream>
 2 using namespace std;
 3 
 4 struct mystr//函数在代码区,无论一个类或结构体有多少个对象,它们的函数都是共有的
 5 {
 6     int a;
 7     int b;
 8     void go()
 9     {
10         std::cout << "123456789" << std::endl;
11     }
12 };
13 
14 void main()
15 {
16     std::cout << sizeof(mystr) << std::endl;//8
17         
18     system("pause");
19 }

复习结构体sizeof

struct mystr
{
int a;//4
double b;//8
char c;//1->8

//4+8+8=20
//20%8!=0
//24%8==0
//答案是24
};

 1 #include <iostream>
 2 using namespace std;
 3 
 4 struct mystr
 5 {
 6     int a;//4
 7     double b;//8
 8     char c;//1->8
 9 
10     //4+8+8=20
11     //20%8!=0
12     //24%8==0
13     //答案是24
14 };
15 
16 void main()
17 {
18     std::cout << sizeof(mystr) << std::endl;//24
19         
20     system("pause");
21 }

class myclass
{
int a;//4
int b;//4
double c;//8

//4+4+8=16
//16%8==0
//答案是16
};

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class myclass
 5 {
 6     int a;//4
 7     int b;//4
 8     double c;//8
 9 
10     //4+4+8=16
11     //16%8==0
12     //答案是16
13 };
14 
15 void main()
16 {
17     std::cout << sizeof(myclass) << std::endl;//16
18         
19     system("pause");
20 }

class myclass
{
int a;//4
double c;//8
int b;//4->8

//4+8+8=20
//20%8!=0
//24%8==0
//答案是24
};

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class myclass
 5 {
 6     int a;//4
 7     double c;//8
 8     int b;//4->8
 9     
10     //4+8+8=20
11     //20%8!=0
12     //24%8==0
13     //答案是24
14 };
15 
16 void main()
17 {
18     std::cout << sizeof(myclass) << std::endl;//24
19         
20     system("pause");
21 }

引用的sizeof,与引用的对象类型有关。不同于指针

//引用的本质是指针,直接sizeof引用,就是求引用的数据大小
//引用变量占据4个字节

 1 #include <iostream>
 2 using namespace std;
 3 
 4 void main()
 5 {
 6     int num = 10;
 7     double db = 10.9;
 8 
 9     int &rnum(num);
10     double &rdb(db);
11     
12     std::cout << sizeof(rnum) << " " << sizeof(rdb) << std::endl;//4 8
13         
14     system("pause");
15 }

class myclass
{
int &a;//4
int &b;//4
char &c;//1

//4+4+1=9
//9%4!=0
//12%4==0
//答案是12
};

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class myclass
 5 {
 6     int &a;//4
 7     int &b;//4
 8     char &c;//1
 9 
10     //4+4+1=9
11     //9%4!=0
12     //12%4==0
13     //答案是12
14 };
15 
16 void main()
17 {
18     std::cout << sizeof(myclass) << std::endl;//12
19         
20     system("pause");
21 }

//引用的本质是指针,直接sizeof引用,就是求引用的数据大小
//引用变量占据4个字节

 1 #include <iostream>
 2 using namespace std;
 3 
 4 //引用的本质是指针,直接sizeof引用,就是求引用的数据大小
 5 //引用变量占据4个字节
 6 
 7 class myclass
 8 {
 9     char a;//1
10     char b;//1
11     char c;//1
12 };
13 
14 class myclass1
15 {
16     char &a;//4
17     char &b;//4
18     char &c;//4
19 };
20 
21 void main()
22 {
23     std::cout << sizeof(myclass) << " " << sizeof(myclass1) << std::endl;//3 12
24         
25     system("pause");
26 }

//引用右值,节约内存拷贝,内存优化

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int getdata(int && num)//引用右值,节约内存拷贝,内存优化
 5 {
 6     std::cout << num << std::endl;
 7     num += 10;
 8     return num;
 9 }
10 
11 void main()
12 {
13     int a(5);
14 
15     std::cout << getdata(a + 1) << std::endl;
16 
17     system("pause");
18 }

左值,一般可以取地址就是左值

右值某些情况可以,某些情况不可以

1>main.cpp(16): error C2664: “int getdata(int &&)”: 无法将参数 1 从“int”转换为“int &&”
1> main.cpp(16): note: 无法将左值绑定到右值引用

std::move将左值转换为右值,C++新语法

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int getdata(int && num)//引用右值,节约内存拷贝,内存优化
 5 {
 6     std::cout << num << std::endl;
 7     num += 10;
 8     return num;
 9 }
10 
11 void main()
12 {
13     int a(3);
14     int b(a + 1);
15 
16     //std::cout << getdata(a) << std::endl;
17 
18     //1>main.cpp(16) : error C2664 : “int getdata(int &&)” : 无法将参数 1 从“int”转换为“int &&”
19     //    1>  main.cpp(16) : note : 无法将左值绑定到右值引用
20 
21     std::cout << getdata(std::move(a)) << std::endl;//std::move将左值转换为右值
22 
23     system("pause");
24 }

//限定字符串不被修改,指向常量的指针限定了指向的数据无法修改

//error C3892: “pc”: 不能给常量赋值

限定一个字符串不被修改,用const char

 1 #include <iostream>
 2 using namespace std;
 3 
 4 void main()
 5 {
 6     char str[10]("hello");
 7     const char *pc(str);//限定字符串不被修改,指向常量的指针限定了指向的数据无法修改
 8 
 9     std::cout << str << std::endl;//hello
10     std::cout << pc << std::endl;//hello
11 
12     str[3] = 'x';
13 
14     //pc[3] = 'y';//error C3892: “pc”: 不能给常量赋值
15     //*(pc + 3) = 'y';//error C3892: “pc”: 不能给常量赋值
16 
17     pc = "world";//可以修改
18 
19     std::cout << str << std::endl;//helxo
20     std::cout << pc << std::endl;//world
21     
22     system("pause");
23 }

//error C3892: “pc”: 不能给常量赋值

限定一个数组不被修改,常量引用一个数组

 1 #include <iostream>
 2 using namespace std;
 3 
 4 void main()
 5 {
 6     char str[10]("hello");
 7 
 8     const char(&rstr)[10](str);//常量引用
 9 
10     std::cout << str << std::endl;
11     std::cout << rstr << std::endl;
12 
13     str[4] = 'x';
14 
15     rstr[4] = 'x';//error C3892: “rstr”: 不能给常量赋值
16 
17     std::cout << str << std::endl;
18     std::cout << rstr << std::endl;
19 
20     system("pause");
21 }

//引用可以给另外一个引用初始化

 1 #include <iostream>
 2 using namespace std;
 3 
 4 void main()
 5 {
 6     char str[10]("hello");
 7 
 8     const char(&rstr)[10](str);//常量引用
 9     const char(&rrstr)[10](rstr);//引用可以给另外一个引用初始化
10 
11     std::cout << str << std::endl;
12     std::cout << rstr << std::endl;
13     std::cout << rrstr << std::endl;
14 
15     system("pause");
16 }

int(*const & rp)(int a, int b)(p);//引用一个函数指针,限定函数指针不被修改

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int jia(int a, int b)
 5 {
 6     return a + b;
 7 }
 8 
 9 int jian(int a, int b)
10 {
11     return a - b;
12 }
13 
14 void main()
15 {
16     int(*p)(int a, int b)(jia);//创建一个函数指针,并初始化
17 
18     int(*const & rp)(int a, int b)(p);//引用一个函数指针,限定函数指针不被修改
19 
20     std::cout << rp(1, 2) << std::endl;
21 
22     rp = jian;//error C3892: “rp”: 不能给常量赋值
23 
24     std::cout << rp(1, 2) << std::endl;
25 
26     system("pause");
27 }
原文地址:https://www.cnblogs.com/denggelin/p/5647789.html