前言:更多内容请看总纲《嵌入式C/C++学习路》
1. 引用定义
引用即别名 int a = 10; int& b = a; // 这里&不是取地址的意思,是引用的意思。 b是一个int型的引用,引用a int& c = b;
引用必须初始化 int& b; // error!!! int& b = a; const int& b = 10;
#include <iostream>
using namespace std;
int main()
{
int a = 10;
int &b = a;
cout << b << endl;
++b;
cout << a << endl;
int d = 20;
b = d;
cout << a << endl;
return 0;
}
2. 把引用作为参数
引用型参数,函数的形参是实参的别名 ——在函数中修改实参值 ——避免对象复制的开销
常引用型参数 ——接受常量型实参 ——防止对实参的意外修改
例子:定义一个函数,交换两个参数a,b的值
#include <iostream>
using namespace std;
void swap1(int a, int b)
{
int c = a;
a = b;
b = c;
}
int main(void)
{
int a = 100, b = 200;
swap1(a, b);
cout << a << ' ' << b << endl;
}
发现这样并不能实现这个功能,因为函数实现的是形参的交换,对实参没有影响。修改如下:
分别通过指针和引用实现:
#include <iostream>
using namespace std;
void swap1(int a, int b)
{
int c = a;
a = b;
b = c;
}
void swap2(int *a, int *b)
{
int c = *a;
*a = *b;
*b = c;
}
void swap3(int &a, int &b)
{
int c = a;
a = b;
b = c;
}
int main(void)
{
int a = 100, b = 200;
swap3(a, b);
cout << a << ' ' << b << endl;
}
再来看一个例子:交换两个字符串(引用指针)
#include <iostream>
using namespace std;
void swap(const char *x, const char *y)
{
const char *z = x;
x = y;
y = z;
}
void swap2(const char **x, const char **y)
{
const char *z = *x;
*x = *y;
*y = z;
}
void swap3(const char *&x, const char *&y)
{
const char *z = x;
x = y;
y = z;
}
int main()
{
const char *x = "Hello world!";
const char *y = "Hello C++";
swap3(x, y);
cout << x << ' ' << y << endl;
return 0;
}
引用还可以用在结构里:
#include <iostream>
using namespace std;
struct Student
{
char name[256];
int age;
};
void print(const Student &s)
{
cout << s.name << ' ' << s.age << endl;
}
int main(void)
{
Student s = {"小明", 26};
print(s);
}
需要注意的是,实参是常量时,定义函数的形参引用需要加const:
#include <iostream>
using namespace std;
struct Student
{
char name[256];
int age;
};
void print(const Student &s)
{
cout << s.name << ' ' << s.age << endl;
}
void show(const int& i){
cout << i << endl;
}
int main(void)
{
Student s = {"小明", 26};
print(s);
show(100);
}
3.引用型返回值
在C++11中可以取地址的、有名字的就是左值,反之,不能取地址的、没有名字的就是右值
引用型返回值,从函数中返回引用,一定要保证在函数返回以后,该引用的目标依然有效 ——返回左值 ——可以返回全局、静态乃至成员变量的引用 ——可以返回在堆中动态创建的对象的引用 ——可以返回调用对象自身的引用 ——可以返回引用型参数本身 ——不能返回局部变量的引用
常引用型返回值 ——返回右值
关于左值右值请参考《C++11 左值、右值、右值引用详解》
来看一个例子(返回左值):
#include <iostream>
using namespace std;
int x;
int &foo(void)
{
return x;
}
int main(void)
{
foo() = 10;
cout << x << endl;
++foo();
cout << x << endl;
foo() += 10;
cout << x << endl;
return 0;
}
返回成员变量的引用:
#include <iostream>
using namespace std;
struct Student{
char name[256];
int age;
int& howold(void){
return age;
}
};
int main(void)
{
Student s = {"张三",22};
int x = s.howold();
cout << x << endl;
return 0;
}
返回引用型参数本身:
#include <iostream>
using namespace std;
int& fun(int& r){
return r;
}
int main(void)
{
int y = 100;
int& r = fun(y);
++r;
cout << y << endl;
return 0;
}
常引用型返回值,返回右值
#include <iostream>
using namespace std;
int x = 10;
const int &foo(void)
{
return x;
}
int main(void)
{
cout << foo() << endl;
return 0;
}
4. 引用的本质
在实现层面,引用就是指针,但在语言层面,引用不是实体类型,因此与指针存在明显的差别:
- 指针可以不初始化,其目标可在初始化后随意变更(除非是指针常量),而引用必须初始化,且一旦初始化就无法变更目标
- 存在空指针,不存在空引用
- 存在指向指针的指针,不存在引用引用的引用
- 存在引用指针的引用,不存在指向引用的指针
- 存在指针数组,不存在引用数组,但存在数组引用
5. 显式类型转换
定义:显式转换也叫强制转换,是自己主动让这个类型转换成别的类型
- C风格的显式类型转换-(目标类型)源类型变量
- C++风格的显式类型转换-目标类型(源类型变量)
- 静态类型转换
- ——static_cat<目标类型>(源类型变量)
- ——隐式类型转换的逆变换
- ——自定义类型转换
#include <iostream>
using namespace std;
int main(void)
{
int *pi;
void *pv = pi;
pi = static_cast<int *>(pv);
return 0;
}
- 动态类型转换
- ——dynamic_cast<目标类型>(源类型变量)
- ——多态父子类指针或引用之间的转换
后面继承和多态再作介绍
- 常类型转换
- ——const_cast<目标类型>(源类型变量)
- ——去除指针或引用上的const属性
#include <iostream>
using namespace std;
int main(void)
{
const int *p1;
int* p2 = const_cast<int*>(p1);
return 0;
}
- 重解释类型转换
- ——reinterpret_cast<目标类型>(源类型变量)
- ——任意类型的指针或引用之间的转换
- ——任意类型的指针和整型之间的转换
#include <iostream>
using namespace std;
struct Student
{
char name[256];
int age;
};
int main(void)
{
Student s = {"张三",22};
char *ps = reinterpret_cast<char*>(&s);
cout << ps << endl;
return 0;
}
|