本文主要是介绍引用和类型强转,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
引用
引用的特点
• 引用 即内存的 别名int a = 10;
int& b = a;• 引用本身 不占内存,并非实体, 对 引用 的所有操作都是在对 目标内存 进行操• 引用必须初始化,且不能更换 目标---> int c = 20;
--->b = c;// 仅仅是在对引用的 目标内存 进行赋值
• 不存在引用的引用– int a = 10;
int & b = a;
int & d = b; //这仅仅是在给a取别名为b和d• 引用的常属性须和目标的常属性“ 一致 ”– const int e = 10;int& f = e;//ERROR
const int& g = e;//OK
• 可以限定更加严格– int a = 10;const int& h = a;//OK
代码演示
//引用
#include<iostream>
using namespace std;
int main(){int a = 10;int& b = a;//不要理解为利用a的数据给b赋值,而是理解为b是a所代表内存的别名b = 20;//表面上是给b赋值,实际上是对a所代表内存的赋值cout << "a = " << a << endl;cout << "b = " << b << endl;//表面上是输出b的值,实际上读取的是a所代表内存的值cout << "&a:" << &a << endl;cout << "&b:" << &b << endl;//a和b指向同一块内存int c = 30;b = c;cout << "a = " << a << endl;cout << "&a:" << &a << ' ' << "&b:" << &b << ' ' << "&c:" << &c << endl;int& d = b;//b是a的别名,所以d也是a的别名(不要理解为引用的引用!!!)cout << "&a:" << &a << ' ' << "&b:" << &b << ' ' << "&d:" << &d << endl;const int e = 40;//int& f = e;//error,去引用时,可以对原类型限定更严格,但不能宽松const int& g = e;//可以给const int取常量引用const int& h = a;//别名可以比真名限定更严格return 0;
}
引用的作用
• 引用可以延长 右值 的 生命周期
• 常引用 即 万能引用
• 引用的 生命周期 不能长于 目标
代码演示
// 左值/右值 和 引用
#include <iostream>
using namespace std;
int foo() {int m=10;return m;
}
int main( void ) {
// 当前作用域的生命期
// 具名内存-->能够取址-->左值|非常左值(无const修饰)
// |常左值 (有const修饰)int a = 10;int& ra = a; // okconst int& cra = a; // okconst int b = 10;
// int& rb = b; // errconst int& crb = b; // ok// 语句级的生命期(引用可以延长右值的生命期)
// 匿名内存-->不能取址-->右值|98/03标准给出的结论:更改右值毫无意义
// |const int& ri = 10; // 取别名后数据10的生命周期延长为当前别名的生命周期 const int& rf = /*|10|*/ foo(); // (1)分配一块匿名内存 (2)生成跳转指令return 0;
}
引用的应用
引用型参数
引用型参数,函数的形参是实参的别名,避免对象复制的开销
• 非常 引用型参数– 在函数中 修改 实参值• 常 引用型参数– 防止 对实参的 意外 修改– 接受 常量型 实参
代码演示
//引用作为函数的形参
#include <iostream>
using namespace std;
void swap(int& x,int& y){ //非常引用型参数:函数内部可以修改实参int temp = x;x = y;y = temp;cout << "x = " << x << " y = " << y <<endl;
}
void swap(int* x,int* y){int temp = *x;*x = *y;*y = temp;cout << "x = " << *x << " y = " << *y << endl;
}
void Print(const int& x,const int& y){ //常引用型参数//x = 10;cout << "x = " << x << " y = " << y << endl;
}int main(){int a = 10;int b = 20;//swap(&a, &b);swap(a, b);Print(a, b);Print(10, 30);return 0;
}
引用型返回值
•引用型的返回值,从函数中返回引用,一定要保证在函数返回以后,该引用的目标依然有效– 可以返回 全局 、 静态 变量的引用– 可以返回在 堆 中 动态创建 的对象的引用– 可以返回 引用型 参数 本身– 不能返回 局部 变量 的引用• 非常 引用型返回值– 通过引用可以修改目标• 常 引用型返回值–通过引用不能修改目标
代码演示
//引用型返回值
#include <iostream>
using namespace std;
int g_value = 10;
int& func(){//返回全局变量的引用 //非常引用型返回值,通过引用可以修改目标return g_value;
}
const int& fun(){//常引用型返回值,通过这个引用不可以修改目标return g_value;
}
int& func2(){//返回静态变量的引用static int s_value = 10;//程序启动就执行,而且只执行一次cout << "s_value = " << s_value << endl;return s_value;
}
int& hum() {int *pn = new int(10); // 在堆上分配一个整数并初始化为10return *pn; // 返回该整数的引用
}
int& pfunc(int& x){return x;//返回引用型参数本身
}
int& boo(){int m = 10;return m; // 返回局部变量的引用(这是错误的,函数结束时m被销毁)!!!
}
int main(){func() = 20;cout << g_value << endl;func2() = 100;func2(); //输出100//返回堆中创建对象的引用int& ref = hum(); // 获取堆上对象的引用cout << "Initial value: " << ref << endl; // 输出10ref = 90; // 修改堆上对象的值cout << "Modified value: " << ref << endl; // 输出90delete &ref; // 手动释放堆上分配的内存//返回引用型参数的引用int v_tomato = 999;pfunc(v_tomato) = 888;cout << "v_tomato = " << v_tomato << endl;return 0;
}
引用与指针的比较
• 在实现层面,引用就是指针,但在 C++ 语言层面,引用不是 实体 类型,因此 C++ 语言层面引用与指针存在明显的差别1. 指针可以 不初始化 , 而引用 必须 初始化。2. 指针的目标可在初始化后 随意变更 ( 除非是指针常量 ) ,而引用一旦初始化就 无法变更 其目标3. 存在空指针,不存在 空引用4. 存在指向指针 的 指针, 不 存在 引用 的 引用5. 存在指针 的引用 , 不 存在 引用 的 指针6. 存在指针 数组 ,不存在 引用 数组 ,但存在 数组 引用
代码演示
//引用 和 指针 的差别
#include <iostream>
using namespace std;int main( void ) {int a=10, b=20;int* p = &a; // 指针可以不做初始化,也可做初始化p = &b; // 指针的目标内存可以随意变更int& r = a; // 引用必须初始化r = b; // 这句代码不会变更 r 所引用的目标内存int** ppa = &p; // 存在二级指针
// int&& rra = r; // 不存在二级引用int*& rpa = p; // 存在指针的引用
// int&* pra = &r; // 不存在引用的指针int x,y,z;int* arr[3] = {&x,&y,&z}; // 存在指针的数组
// int& rra[3] = {x,y,z}; // 不存在引用的数组int m[3];int(&q)[3] = m;// 存在数组的引用return 0;
}
类型强转
显示类型转换
• C 风格的显式类型转换– ( 目标类型 ) 源类型变量• C++ 风格的显式类型转换– 目标类型 ( 源类型变量 )• 静态类型转换– static_cast < 目标类型 > ( 源类型变量 )– 隐 式类型转换的逆转换• 常类型转换– const_cast < 目标类型 > ( 源类型变量 )– 去除指针或引用上的 const 属性• 重 解释类型转换– reinterpret_cast < 目标类型 > ( 源类型变量 )– 任意类型的指针之间的转换或引用之间的转换– 任意类型的指针和整型之间的转换
代码演示
// 显式类型转换(强转)
#include <iostream>
using namespace std;int main( void ) {int a; double b; float c; short d; char e;// 任何基本类型的变量之间都可以隐式转换a = b = c = d = e;e = d = c = b = a;// 任何其他类型的指针 到 void* 都可以隐式转换void* pv = &a; // int*-->void*pv = &b;pv = &c;pv = &d;pv = &e;// void* 到 任何其他类型的指针 都必须强转***************int* pa = static_cast<int*>(pv); // void*-->int*的反向int*-->void*可以隐式double* pb = static_cast<double*>(pv);float* pc = static_cast<float*>(pv);short* pd = static_cast<short*>(pv);char* pe = static_cast<char*>(pv);// 任何类型非常指针 到 同类型常指针 都可以隐式转换const int* cpa = pa; // int*-->const int*const double* cpb = pb;const float* cpc = pc;const short* cpd = pd;const char* cpe = pe;// 任何类型常指针 到 同类型非常指针 都必须强转**************pa = const_cast<int*>(cpa); pb = const_cast<double*>(cpb);pc = const_cast<float*>(cpc);pd = const_cast<short*>(cpd);pe = const_cast<char*>(cpe);// 除了void*外,其他类型指针之间 都必须强转*******************pb = reinterpret_cast<double*>(pa); pb = reinterpret_cast<double*>(1000);return 0;
}
这篇关于引用和类型强转的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!