c++基本使用(引用)

概念

引用是已定义的变量的别名。
引用的主要用途是用作函数的形参和返回值。
声明/创建引用的语法:

数据类型 &引用名=原变量名;

 引用的数据类型要与原变量名的数据类型相同。
 引用名和原变量名可以互换,它们值和内存单元是相同的。
 必须在声明引用的时候初始化,初始化后不可改变。
C和C++用&符号来指示/取变量的地址,C++给&符号赋予了另一种含义

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。

int main()
{
	// 声明 / 创建引用的语法:数据类型 & 引用名 = 原变量名;
	int a = 3;          // 声明普通的整型变量。
	int& ra = a;      // 创建引用ra,ra是a的别名。
	
	cout << " a的地址是:" << &a  <<"\t"<< "a的值是:" <<  a  << endl;
	cout << " ra的地址是:" << &ra <<"\t"<< "ra的值是:" << ra << endl;
	
	ra = 5;    

	cout << " a的地址是:" << &a << "\t"<<"a的值是:" << a << endl;
	cout << " ra的地址是:" << &ra << "\t"<<"ra的值是:" << ra << endl;
}

引用的本质

引用是指针常量的伪装。(引用和指针本质上没有区别)

引用是编译器提供的一个有用且安全的工具,去除了指针的一些缺点,禁止了部分不安全的操作。

程序员拥有引用,但编译器仅拥有指针(地址)。

引用的底层机制实际上是和指针一样的,编译器还是会把引用解释为指针。

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。

int main()
{
	// 声明 / 创建引用的语法:数据类型 & 引用名 = 原变量名;
	// 语法:数据类型 * const 变量名;
	int a = 3;                         // 声明普通的整型变量。
	int& ra = a;                    // 创建引用ra,ra是a的别名。               把int&替换成int* const   把a替换成&a
	int* const rb = &a;        // 声明指针常量rb,让它指向变量a。
	
	cout << " a的地址是:" << &a  << "    a的值是:" <<  a  << endl;
	cout << " ra的地址是:" << &ra << "   ra的值是:" << ra << endl;     // 把&ra替换成ra,把ra替换成*ra
	cout << " rb的值是  :" << rb << "    *rb的值是:" << *rb << endl;
	
	ra = 5;    

	cout << " a的地址是:" << &a << "    a的值是:" << a << endl;
	cout << " ra的地址是:" << &ra << "   ra的值是:" << ra << endl;
	cout << " rb的值是  :" << rb << "    *rb的值是:" << *rb << endl;
}

引用使用于函数的参数

按引用传递:把函数的形参声明为引用,调用函数的时候,形参将成为实参的别名。
(传值、传地址、传引用只是说法不同,其实都是传值)

引用的本质是指针,传递的是变量的地址,在函数中,修改形参会影响实参。

传递值、传递地址、传递引用的区别:

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。

void func1(int no, string str)    // 传值。
{
	no = 8; 
	str = "我有一只小小鸟。";
	cout << "亲爱的" << no << "号:" << str << endl;
}

void func2(int* no, string* str)    // 传地址。
{
	*no = 88;
	*str = "我有一只小小鸟。";
	cout << "亲爱的" << *no << "号:" << *str << endl;
}

void func3(int &no, string &str)    // 传引用。
{
	no = 888;
	str = "我有一只小小小小鸟。";
	cout << "亲爱的" << no << "号:" << str << endl;
}

int main()
{
	int bh = 3;      // 超女的编号。
	string message = "我是一只傻傻鸟。";          // 向超女表白的内容。

	func1(bh, message);                  // 传值。
    cout << "亲爱的" << bh << "号:" << message << endl;
    cout<<endl;

	func2(&bh, &message);            // 传地址。
    cout << "亲爱的" << bh << "号:" << message << endl;
    cout<<endl;

	func3(bh, message);                  // 传引用。
    cout << "亲爱的" << bh << "号:" << message << endl;
    cout<<endl;
	
}

对于结构体,传递值、传递地址、传递引用的区别:

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。

struct st_girl      // 定义超女结构体。
{
	int no;            // 超女编号。
	string str;      // 表白内容。
};

void func1(st_girl girl)    // 传值。
{
	girl.no = 8;
	girl.str = "我有一只小小鸟。";
	cout << "亲爱的" << girl.no << "号:" << girl.str << endl;
}

void func2(st_girl *girl)    // 传地址。
{
	girl->no = 88;
	girl->str = "我有一只小小鸟。";
	cout << "亲爱的" << girl->no << "号:" << girl->str << endl;
}

void func3(st_girl & girl)    // 传引用。
{
	girl.no = 888;
	girl.str = "我有一只小小小小鸟。";
	cout << "亲爱的" << girl.no << "号:" << girl.str << endl;
}

int main()
{
	st_girl girl = { 3,"我是一只傻傻鸟。" };

	func1(girl);                  // 传值。
    cout << "亲爱的" << girl.no << "号:" << girl.str << endl;
    cout<<endl;

	func2(&girl);            // 传地址。
    cout << "亲爱的" << girl.no << "号:" << girl.str << endl;
    cout<<endl;
	
    func3(girl);                  // 传引用。
    cout << "亲爱的" << girl.no << "号:" << girl.str << endl;
    cout<<endl;
	
}

传递一级指针,在函数中动态开辟内存空间:

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。

void func1(int** p)      // 传地址,实参是指针的地址,形参是二级指针。
{
	*p = new int(3);       // p是二级指针,存放指针的地址。
	cout << "func1内存的地址是:" << *p << ",内存中的值是:" << **p << endl;
}

void func2(int*& p)     // 传引用,实参是指针,形参是指针的别名。
{
	p = new int(3);         // p是指针的别名。
	cout << "func2内存的地址是:" << p << ",内存中的值是:" << *p << endl;
}

int main()
{
	int* p = nullptr;    // 存放在子函数中动态分配内存的地址。

	func1(&p);      // 传地址,实参填指针p的地址。
    cout << "main 内存的地址是:" << p << ",内存中的值是:" << *p << endl;
    cout<<endl;

	func2(p);      // 传引用,实参填指针p。
	cout << "main 内存的地址是:" << p << ",内存中的值是:" << *p << endl;
    cout<<endl;
    
	delete p;
}

引用的形参和const

将引用形参声明为const的理由有三个:
 使用const可以避免无意中修改数据的编程错误。
 使用const使函数能够处理const和非const实参,否则将只能接受非const实参。
 使用const,函数能正确生成并使用临时变量。

	//如果引用的数据对象类型不匹配,当引用为const时,C++将创建临时变量,让引用指向临时变量。
    const int& a = 8;
    //等效于下面的代码
    int tem = 8;
    const int& p = tem;

在形参是指针变量或引用的时候;不能传值,只能传递地址或变量名
为了解决这个问题,就在引用的前面加上const (但指针还是不能传递值)

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。

void func1(int no, string str)    // 传值。
{
	cout << "亲爱的" << no << "号:" << str << endl;
}

void func2(const int* no,const string* str)    // 传地址。
{
	cout << "亲爱的" << *no << "号:" << *str << endl;
}

void func3(const int& no, const string& str)    // 传引用。
{
	cout << "亲爱的" << no << "号:" << str << endl;
}

int main()
{
	int bh = 3;      // 超女的编号。
	string message = "我是一只傻傻鸟。";          // 向超女表白的内容。

    func1(bh, message);                  // 传值。
	func2(&bh, &message);            // 传地址。
	func3(bh, message);                  // 传引用。


    cout<<"不声明普通变量;直接传递值,调用函数"<<endl;	
	func1(8, "我是一只小小鸟。");
	//func2(8, "我是一只小小鸟。"); //不能传递数字
	func3(80, "我是一只小小鸟。"); //可以传递数字


	//如果引用的数据对象类型不匹配,当引用为const时,C++将创建临时变量,让引用指向临时变量。
    const int& a = 8;
    //等效于下面的代码
    int tem = 8;
    const int& p = tem;
}

引用用于函数的返回值

传统的函数返回机制与值传递类似。
函数的返回值被拷贝到一个临时位置(寄存器或栈),然后调用者程序再使用这个值。

问题:占用内存空间。。
解决方案:返回地址或者返回引用不会拷贝内存。
语法返回值的数据类型& 函数名(形参列表);

注意
 如果返回局部变量的引用,其本质是野指针,后果不可预知。
 可以返回函数的引用形参、类的成员、全局变量、静态变量。
 返回引用的函数是被引用的变量的别名,将const用于引用的返回类型。

被引用变量的生命周期一定得比引用长

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。

int func1(){
    return 1;
}

int& func3()    // 返回的是引用。
{
    //局部变量的引用,其本质是野指针
    int ii = 3;
	return ii;
}
int& func31()    // 返回的是引用。
{
    //引用静态变量
    static int ii = 3;
	return ii;
}
//引用全局变量
int iii = 3;
int& func32()    // 返回的是引用。
{
	return iii;
}
int& func33()    // 返回的是引用。
{
    int ii = 3;
	return ii;
}

int& func2(int &ra)    // 返回的是引用。
{
	ra++;
	cout << "ra的地址是:" << &ra << ",ra=" << ra << endl;
	return ra;
}

const int& func22(int &ra)    // 返回的是引用。
{
	ra++;
	cout << "ra的地址是:" << &ra << ",ra=" << ra << endl;
	return ra;
}

int main()
{
    cout<<"返回值"<<endl;
    cout<<func1()<<endl;

    //返回局部变量的引用,其本质是野指针(局部变量被释放掉了)
    cout<<"返回局部变量的引用"<<endl;
    int& b1 = func3();
    cout<<"局部变量被释放,主函数中的引用变成了野指针\t";
    cout<<b1<<endl;
    
    cout<<"返回静态变量的引用"<<endl;
    int& b31 = func31();
    cout<<b31<<endl;

    cout<<"返回静态变量的引用"<<endl;
    int& b32 = func32();
    cout<<b32<<endl;


    cout<<"函数的引用形参"<<endl;
	int a = 3;
	int& b = func2(a);      // 返回的是引用。

	cout << " a的地址是:" << &a << ", a=" << a << endl;
	cout << " b的地址是:" << &b << ", b=" << b << endl;
    cout<<"可以看出,传递的变量,函数的参数,返回值都是指向同一个变量"<<endl;

    cout<<"返回引用的函数是被引用的变量的别名,因此,func2(a) = 10等价于:a = 10"<<endl;
	func2(a) = 10;             // 返回引有的函数是被引用的变量的别名。

	cout << " a的地址是:" << &a << ", a=" << a << endl;
	cout << " b的地址是:" << &b << ", b=" << b << endl;

    cout<<"返回引用的函数是被引用的变量的别名,如不不希望返回值被当成变量来使用,就在返回值前面加上const关键字."<<endl;
    //func22(a) = 100; //不能当变量用了,所以报错;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值