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 }