c++------引用(左值与右值,引用一个数组,const限制)

&与&&
  对于在C++中,大家对于符号“ & ”的第一映像是引用和取地址,对符号“ && ”的第一映像是逻辑与。但是在C++11中我们会看到下方这种表示方法:

int &&k=i+k;
1
  对于第一眼见到上述的表达方式时,估计会一脸懵逼。下面对此做一个简述。
  引用 & 是一个类型变量的别名。
  通常使用 “ & ”是作为普通的左值引用,左值是可以放在赋值号 “ = ”的左边的值。
  &&是右值引用,右值是只能放在 “ = ” 右边的值,右值没有一个 “ 变量 ”名字。如:

int && k =i+j;
1
  i+j 返回的值可以视做是放在一个临时存放内存空间里的,这个空间并不能用来赋值,你不能些i+j=5等; && 可以把这种临时的值和存在变量里的值区分开来。
  右值短暂,右值只能绑定到临时对象。所引用的对象将要销毁或对象没有其他用户。
  初始化时右值引用一定要用一个右值表达式绑定,初始化之后,可以用左值表达式或修改右值引用的所引用临时对象的值。
  右值引用是对临时对象的一种引用,它是在初始化时完成引用的,但是右值引用不代表引用临时对象后,就不能改变右值引用所引用对象的值。仍然可以在初始化后改变临时对象的值。

  对于引用类型,可以用于它所引用对象类型的可以用的地方(把他当成普通变量),只不过用到的值是它所引用的对象的值,还可以用于移动构造和赋值函数的地方。

例子

#include <algorithm>
#include <iostream>
#include <functional>
#include <vector>
#include <numeric>
#include <array>
#include <cstring>
#include <cstdio>
#include <windows.h>
using namespace  std;
//c++能用引用的情况就不要用指针


int main1()
{    
    int num = 10;//num左值,内存实体
    int& rnum(num);//变量的别名
    rnum = 1;//rnuum等价于num的别名
    cout << num << endl;//1
    system("pause");
}
////右值引用 ,节约内存,快速引用寄存器的值
int main()
{
    int num = 1;
    int &&rnum(num + 4);//右值引用,快速备份,编译器自动回收
    printf("%p",&rnum);
    int data = num+4;
    int &rdata(data);//左值引用
    cout << (void*)&data << endl;
    
    data=num+1;
}
void main()
{
    int a[5] = { 1, 2, 3, 4, 5 };
    int *p(a);
    //cout << *p << endl;//1
    //int* &rp(p);//左值引用改变指针
    //rp += 1;
    //cout << *p << endl;//2
    int *&&rrp(p+2);//右值引用&&
    cout << *rrp << endl;//3
    rrp += 2;
    cout << *rrp << endl;//5

}
void showit(int&& rrnum)
{
    cout << rrnum << endl;
}
//左值应用往往引用的是内存里面的值,而右值引用一般是寄存器里面的值
void  main()
{
    int a[5] = { 1, 2, 3, 4, 5 };
    showit(a[3] + 2);//5,右值引用大大节约内存
    showit(move(a[3]));//move移动语义,左值变长右值
}

  

引用的本质:

#include <algorithm>
#include <iostream>
#include <functional>
#include <vector>
#include <numeric>
#include <array>
#include <cstring>
#include <cstdio>
#include <windows.h>
using namespace  std;
void  main1()
{
    int num = 10;
    int data = 20;
    int & rnum(num);//引用一旦初始化,不会再引用其他的变量
    rnum = data;
    cout << num << endl;//20
    cout << data << endl;20
}
void main()
{
    double db;
    double&rdb(db);
    cout << sizeof(rdb) << endl;//8,编译器优化处理,引用变量名的别名
    struct Mystruct //引用的本质是指针实现的,用于简化程序
    {
        double &rdb;
    };
    cout << sizeof(Mystruct) << endl;//4
}

 

 

引用作为参数

#include <algorithm>
#include <iostream>
#include <functional>
#include <vector>
#include <numeric>
#include <array>
#include <cstring>
#include <cstdio>
#include <windows.h>
using namespace  std;
//改变指针需要二级指针
//栈区,自动回收,释放,返回值为指针,不能指向栈区,返回引用,不能引用栈区

int main()
{
    int a(4);//初始化为4
    int*p(new int(5));//初始化为5
    cout << a << endl;//4
    cout << *p << endl;//5
    int &ra(a);//引用变量
    int*&rp(p);//引用指针

    ra = 3;
    *rp = 12;

    cout << a << endl;//3
    cout << *p << endl;//12


    cin.get();
}
int main()
{
    int a(4);//初始化为4
    int*p(new int(5));//初始化为5
    cout << a << endl;//4
    cout << *p << endl;//5

    int&&rra(move((a)));//右值,有内存实体,就直接引用,没有就开辟内存
    int *&&rrp(move(p));
    rra = 1;
    cout << rra <<endl;//1
    cout << a << endl;//1
    
    //int&:引用内存实体,引用整数,本质是指针
    //int&&:引用整数,本质是指针,能处理左值和右值,处理左值需要配合move
    //int:整数类型
    cin.get();
}
int num1 = 10;
int num2 = 20;
void change(int *&rp)
{
    rp = &num2;
}
void main()//c++能用引用就别用指针 
{
    int *p = #
    change(p);
    cout << *p << endl;//20;
}

int main()
{
    int *p(nullptr);
    int**pp = &p;
    int**&rpp = pp;//vs2015
    //vs2013中:int(**(&rpp))(pp);
    //vs2013:int(*(&rpf)),需考虑优先级
}
void main()
{
    //vs2015
    int***ppp(nullptr);
    int***&rppp(ppp);
    //vs2013
    int(***ppp)(nullptr);
    int(***(&rppp))(ppp);
}


int data = 10;
int data2 = 20;
int *p = &data;
void change(int **&rpp)//引用
{
    *rpp = &data2;
}
int main()
{
    int **pp = &p;//二级指针
    cout << **pp << endl;//10;
    change(pp);
    cout << **pp << endl;//20;
}
int& getdata()
{
    int num = 10;//销毁了,调用结束自动销毁
    return num;
}


int main()
{
    //int & rnum = getdata();//引用原来的内存,已经销毁的地方,乱码
    int & rnum = getdata();//拷贝到新的内存
    cout << "hello";
    cout << rnum << endl;
    printf("%d",getdata());//10
}
char*& getcode()
{
    char*p = "hello world";//指向只读数据区
        return p;
}
void  main()
{
    char*&rp = getcode();//引用本质是指针,引用的就是函数中的p,而那个内存可能已经释放
    char*newp = rp;//保存rp存储代码区的地址
    cout << "hello " << endl;
    cout << newp << endl;//输出hello world
    cout << rp << endl;//乱码;
}

  

 

 

引用一个数组及引用数组是非法的

#include <algorithm>
#include <iostream>
#include <functional>
#include <vector>
#include <numeric>
#include <array>
#include <cstring>
#include <cstdio>
#include <windows.h>
using namespace  std;
int main()
{
	int a[5]{1, 2, 3, 4, 5};
	int *pa[5] = { a, a + 1, a + 2, a + 3, a + 4 };
	int b[3][4]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
	int*pb[3][4]{&b[0][0], &b[0][0] + 1, &b[0][0] + 2, &b[0][0]+3,........}
	int *p1(new int[5]{1, 2, 3, 4, 5});//堆上的一维数组

	int(*p2)[4](new int[3][4]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12});//堆上的二维数值
	cin.get();
}

void main()
{
	int a[5]{1, 2, 3, 4, 5};
	//int a[5] == == > int(&ra)[5](a);//引用数组,用a初始化
	int *pa[5] = { a, a + 1, a + 2, a + 3, a + 4 };
	int(&ra)[5](a);//引用数值
	int*(&rpa)[5](pa);//引用指针数值
	for(auto& i:ra)
	{
		cout << i+=1 << endl;//会修改数据
	
	}
	for (auto i:rpa)
	{
		cout << *i << endl;
	}
}
void main()
{
// 	int *p1(new int[5]{1, 2, 3, 4, 5});//堆上的一维数组
// 	int **pp ( new int*[5]{p1,p1+1,p1+2,p1+3,p1+4});//堆上的指针数组
// 	int*&rp(p1);
// 	int **&rpp(pp);//vs2015
	//vs2013以下
		int *p1(new int[5]{1, 2, 3, 4, 5});//堆上的一维数组
		int *(*pp) ( new int*[5]{p1,p1+1,p1+2,p1+3,p1+4});//堆上的指针数组
		int(*(&rp))(p1);
	 	int (**(&rpp))(pp);
	for (int i = 0; i < 5;i++)
	{
		cout << rp[i] << endl;
	}
	for (int i = 0; i < 5; i++)
	{
		cout << *rpp[i] << endl;
	}
}
void main()
{
	int b[3][4]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
	int*pb[3][4]{&b[0][0], &b[0][0] + 1, &b[0][0] + 2, &b[0][0] + 3, ........}
	int(&rb)[3][4](b);//引用二维数值
	int *(&rpb)[3][4](pb);
	for (int i=0;i<3;i++)
	{
		for (int j = 0; j < 4; j++)
		{
			cout << rb[i][j];
		}
	}
	for (int i = 0;i < 3;i++)
	{
		for (int j = 0; j < 4; j++)
		{
			cout << *rpp[i][j];
		}
	}

}
void main()
{
	//指向数组的指针,{}包含
	int(*p2)[4](new int[3][4] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } });//堆上的二维数值
	int(*&rp)[4](p);

	int*(*pp)[4](new int*[3][4]);//在堆上开辟二维指针数值
	int*(*&rpp)[4](pp);//引用二维指针数组
	for (int i = 0;i < 3;i++)
	{
		for (int j = 0; j < 4; j++)
		{
			cout << rp[i][j];
		}
	}

}
 int main)
 {
	 int a = 1;
	 int &ra(a);
	 int b = 2;
	 int &rb(b);
	 int c = 3;
	 int &rc(c);
	 int &myarr[3]{ra, rb, rc};//错误,引用数组非法,只能单独引用
 }

  加const的引用

#include <algorithm>
#include <iostream>
#include <functional>
#include <vector>
#include <numeric>
#include <array>
#include <cstring>
#include <cstdio>
#include <windows.h>
using namespace  std;
void main1()
{
    int num = 100;
    int const& rnum(num);//让别人引用,限定权限,只能读不能写
    //rnum =3//不允许对常量赋值
    cout << rnum << endl;
}
void main2()
{
    int num = 100;
    //int & const rnum(num);// 使用了记时错误: 忽略引用上的限定符,const会被忽略
}
void main3()
{

    int a[5] = { 1, 2, 3, 4, 5 };
    const int(&ra)[5](a);
    for (auto &i:ra)
    {
        //i+=1;//只能读,不能写
        cout << i << endl;//只能读,不能写


    }
    cin.get();
}
void main()
{
    int *p(new int(5));
    //int *&rp(p);
     int (*(&rp))(p);//
    *rp = 3;
    cout << *p << endl;//3
}
void main()
{

    const int *const p(new int(4));
    *p = 1;
    const int*(*const(&rp))(p);//引用一个常量的常量指针
}
void show( const int& p)//明确只读
void main()
{
    int *p(new int(4));
    const int *&rp((const int *&)p);//强转成const int *的引用

}

 

posted @ 2019-08-05 17:16  白伟碧一些小心得  阅读(665)  评论(0编辑  收藏  举报