C++ 引用(2)

引用是c++对c的重要扩充。在c/c++中指针的作用基本都是一样的,但是c++增加了另外一种给函数传递地址的途径,这就是按引用传递(pass-by-reference)

1. 引用基本使用

基本语法

Type& ref = val;

注意事项:

  • &在此不是求地址运算,而是起标识作用。
  • 类型标识符是指目标变量的类型
  • 必须在声明引用变量时进行初始化。
  • 引用初始化之后不能改变。
  • 不能有NULL引用。必须确保引用是和一块合法的存储单元关联。
//1. 认识引用
void test01(){

    int a = 10;
    //给变量a取一个别名b
    int& b = a;
    cout << "a:" << a << endl;
    cout << "b:" << b << endl;
    cout << "------------" << endl;
    //操作b就相当于操作a本身
    b = 100;
    cout << "a:" << a << endl;
    cout << "b:" << b << endl;
    cout << "------------" << endl;
    //一个变量可以有n个别名
    int& c = a;
    c = 200;
    cout << "a:" << a << endl;
    cout << "b:" << b << endl;
    cout << "c:" << c << endl;
    cout << "------------" << endl;
    //a,b,c的地址都是相同的
    cout << "a:" << &a << endl;
    cout << "b:" << &b << endl;
    cout << "c:" << &c << endl;
}
//2. 使用引用注意事项
void test02(){
    //1) 引用必须初始化
    //int& ref; //报错:必须初始化引用
    //2) 引用一旦初始化,不能改变引用
    int a = 10;
    int b = 20;
    int& ref = a;
    ref = b; //不能改变引用
}
// 数组的引用
void test03()
{
    int arr[] = {1,2,3,4,5};
    // 方法1
    // 1.定义数组类型
    typedef int(MY_ARR)[5]; // 数组类型
    // 2.建立引用
    MY_ARR &arref1 = arr;

    // 方法2
    // 直接定义引用
    int (&arref2)[5] = arr;

    // 方法3
    // 1.定义引用数组类型
    typedef int(&MY_ARR_REF)[5];
    // 2.建立引用
    MY_ARR_REF arref3 = arr;
}

2. 引用的本质

引用的本质在c++内部实现是一个常指针.

Type& ref = val; // Type* const ref = &val;

C++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同,只是这个过程是编译器内部实现,用户不可见

// 发现是引用,转换为 int* const ref = &a
void testFunc(int &ref)
{
    ref = 100; // ref 是引用,转换为 *ref = 100;
}
void test01()
{
    int a = 10;
    testFunc(a);
}
void test02()
{
    int a = 10;
    int &aRef = a; // 自动转换为 int * const ref = &a;这就说明引用为什么必须初始化
    aRef = 20;     // 内部发现aRef是引用,自动帮我们转换为:*aRef = 20;
}

3. 指针引用

指针的引用 是给指针变量取别名

在c语言中如果想改变一个指针的指向而不是它所指向的内容,函数声明可能这样:

void fun(int**);
// C语言 二级指针放一级指针变量的地址
// 被调函数
void func2(char **temp)
{
    char *p;
    p = (char *)malloc(64);
    memset(p,0,64);
    strcpy(p, "小花2");
    *temp = p;
}
// 主调函数
void test02()
{
    char* mp = NULL;
    func2(&mp);
    cout << mp << endl;
}

在C++中使用指针引用,去改变一个指针的指向,代码更加简洁

// C++
void func3(char* &temp) {
    char *p;
    p = (char *)malloc(64);
    memset(p,0,64);
    strcpy(p,"小花3");
    temp = p;
}

void test03() {
    char* mp= NULL;
    func3(mp);
    cout << mp << endl;
}

通过引用参数产生的效果同按地址传递是一样的。引用的语法更清楚简单:

  • 函数调用时传递的实参不必加“&”符
  • 在被调函数中不必在参数前加“*”符

4. 常量引用

常量引用的定义格式:

const Type& ref = val;

常量引用注意:

  • 字面量不能赋给引用,但是可以赋给const引用
  • const修饰的引用,不能修改。
void test01()
{
    // 普通引用
    int a = 10;
    int &ref = a;
    ref = 20;

    // int &ref2 = 10; // 普通引用不能给字面量取名 错误

    const int &ref3 = 10; // 可以给const修饰的引用赋予字面量
    // const修饰符修饰的引用的原理
    // 编译器会把上面的代码变为: int tmp = 10; const int &ref3=tmp

    int b = 20;
    const int &ref4 = b; // const修饰的引用,不能修改
    // ref4 = 30;
}

5. 引用的使用场景

常量引用主要用在函数的形参,尤其是类的拷贝/复制构造函数。
将函数的形参定义为常量引用的好处:

  • 引用不产生新的变量,减少形参与实参传递时的开销。
  • 由于引用可能导致实参随形参改变而改变,将其定义为常量引用可以消除这种副作用。

如果希望实参随着形参的改变而改变,那么使用一般的引用,如果不希望实参随着形参改变,那么使用常引用。

//const int& param防止函数中意外修改数据
void ShowVal(const int& param){
    cout << "param:" << param << endl;
}

引用作为函数参数传递数据,节约空间

// 1. 引用作为函数参数传递数据,节约空间

void func1(int &a, int &b)
{
    int sum = a + b;
    cout << "sum = " << sum << endl;
}

引用作为函数的返回值

int &func3() {
    static int b = 10;
    return b;
}

注意:

  • 不要返回局部变量的引用
  • 函数当左值,必须返回引用。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,546评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,224评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,911评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,737评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,753评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,598评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,338评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,249评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,696评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,888评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,013评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,731评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,348评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,929评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,048评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,203评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,960评论 2 355

推荐阅读更多精彩内容