一.左值与右值
左值一般可以取地址,右值某些情况可以,某些情况不可以。
左值就是可以放在赋值号左边被赋值的值,必须要在内存有实体。
右值放在赋值号右边取出值赋值给其他变量的值。右值可以在内存中也可以在cpu。
右值的引用,省去了去寄存器(寄存器不可取地址)到内存的拷贝,直接在寄存器中进行数据操作,节约了内存,内存优化,
左值通过 std::move(变量名); 转换为右值。
#include<iostream>
#include<stdlib.h>
using namespace std;
void main1()///a b在内存中,a+1在寄存器中
{
int a = 5;
int b;
cout << &a << ' '<<&b<<endl;
b = a;
b = a + 1;
system("pause");
}
void main2()//左值引用
{
int a = 3;
int & re(a);
re = 666;
cout << a << endl;
system("pause");
}
void change(int &a)//引用地址,建立变量接收实际参数的值
{
a = 666;
cout << "change addr=" << &a << endl;
}
void main3()//引用的用途
{
int a = 6;
change(a);
cout <<"main"<< &a <<' '<<a<< endl;
system("pause");
}
void main4()//引用指针
{
int num1(5);
int num2(10);
int *pnum(&num1);
int* &rpnum(pnum);
//rpnum = &num2;//改变指针的指向
*rpnum = 100;//改变指针指向的值
cout << *pnum << endl;
cout << num1 << endl;
system("pause");
}
void main5()//
{
int num1(5);
int num2(10);
int * &&pnum(&num1);//引用右值
int* p = pnum;//用于对象拷贝
p = &num1;//取地址在寄存器
p = &num2;
cout << *pnum << endl;//5
cout << num1 << endl;//5
system("pause");
}
int &get()
{
int a = 10;
int & ra = a;
return ra;
}
int* &get1()
{
int* p = new int;//堆上的内存
cout <<"&p="<< &p << endl;//P是一个野指针
*p = 10;
int* &rp = p;
return rp;
}
void main6() //指针p在栈上,p的内容在堆上,
//函数执行后,指针p会消亡,但是堆上的内容会一直保留
{
int &ra = get();
cout << ra << endl;
int* &rp = get1();
int *p = rp;//指向堆上的地址
cout << *rp << endl;//10
cout <<*p << endl;
cout << *rp << endl;//指针位于栈上,内存被回收重新利用
cout << *p << endl;
delete(p);//删除内存后禁止访问
cout << "china" << endl;//堆栈重新利用,内存回收
cout << ra << endl;
system("pause");
}
void main()
{
int a = 10;
int &ra = a;//左值引用
int* &&pa = &a;//右值引用
cout << &a << endl;
cout << pa << *pa << &pa << endl;
system("pause");
}
注:CPP中检测到右值会自动转换为左值
例如:
int num=3;
(num=3)=4;
int num=5;
(num>num1?)num:num1)=2;
右值转换为左值后赋值
二.C++中的引用
1.引用通过 & 表示引用,注:引用必须进行初始化,例如:
int a=10,b=20;
int &rf=a;
iny &re(b);
2.引用的特点:
1>引用不可以重名
2>建立新的变量名,指向的地址一样,操作相同。(别名,取地址,不允许重定义)
3>引用可以改变指针的指向,同时还可以改变指正指向的值,取地址在寄存器中。
4>改变外部变量的值,作为函数调用的参数表,同时还可以通过传递地址的方式。
void change(int &a)
{
a=100;
}
void change1(int *p)
{
p=100;
}
5>左值引用通过指针实现
6>用于对象拷贝
int num=100;
int *&&rpnum=#
int *p=rpnum;
#include<iostream>
#include<stdlib.h>
using namespace std;
void main1()//引用一维和二维数组
{
int a[5] = { 1,2,3,4,5 };
int b[2][5] = { 0 };
int (&ra)[5](a);
int(&rb)[2][5](b);//引用二维数组
int i = 0;
for (auto data : ra)
{
data = i + 5;
cout << data << endl;
}
for (int i = 0;i < 2;i++)
{
for (int j = 0;j < 5;j++)
{
cout << ' ' << rb[i][j];
}
cout << endl;
}
cout << a << ' ' << ra << endl;
system("pause");
}
int add(int a, int b)
{
return a + b;
}
int submit(int a, int b)
{
return a - b;
}
void change(int (* &rp)(int,int))//通过引用,函数改变函数指针的指向
{
rp = submit;
}
int (* &changep(int(*&rp)(int, int)))(int,int)//返回值是函数指针的引用
{
rp = submit;
return rp;
}
void main2()
{
int (*p)(int, int)(add);
cout << p(1, 2) << endl;
p = submit;
cout << p(1, 2) << endl;
int(* &rp)(int,int) = p;//引用一个函数指针
//rp = submit;//改变函数指针的指向
rp=changep(rp);
cout << p(1, 2) << endl;
system("pause");
}
void main3()
{
int a = 1, b = 2, c = 3;
int *p[3] = { &a, &b, &c};
}
struct mystr
{
char a;
int b;
double c;
//代码区的函数不计入结构体的sizeof()
void go()
{
cout << "hahahaha" << endl;
}
};
class myclass
{
int a;
int b;
double c;
};
class myclass1//引用的本质是指针,直接sizeof引用,就是求引用的数据的大小,
//引用变量占据四个字节
{
char & a;
char &b;
char &c;
};
void main4()
{
int num = 10;
int &rnum = num;
double db = 10.9;
double &rdb(db);
cout << sizeof(rnum) << endl;//4
cout << sizeof(rdb) << endl;//8
cout << sizeof(mystr) << endl;//跳过函数只计算数据16, double类型位于int 和 char 前面时是24
cout << sizeof(myclass) << endl;
cout << sizeof(myclass1) << endl;//12
system("pause");
}
int getdata(int &&num)//右值操作在寄存器中
{
cout << num << endl;
num += 10;
return num;
}
void main5()//右值引用
{
int a = 5;
int b = 4;
cout << getdata(a+1) << endl;//右值的调用
system("pause");
}