引用和类型强转

2024-09-01 03:20
文章标签 类型 引用 强转

本文主要是介绍引用和类型强转,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

引用

引用的特点

引用 即内存的 别名  

        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;
}

这篇关于引用和类型强转的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1125801

相关文章

Python中Json和其他类型相互转换的实现示例

《Python中Json和其他类型相互转换的实现示例》本文介绍了在Python中使用json模块实现json数据与dict、object之间的高效转换,包括loads(),load(),dumps()... 项目中经常会用到json格式转为object对象、dict字典格式等。在此做个记录,方便后续用到该方

python中的显式声明类型参数使用方式

《python中的显式声明类型参数使用方式》文章探讨了Python3.10+版本中类型注解的使用,指出FastAPI官方示例强调显式声明参数类型,通过|操作符替代Union/Optional,可提升代... 目录背景python函数显式声明的类型汇总基本类型集合类型Optional and Union(py

MySQL中查询和展示LONGBLOB类型数据的技巧总结

《MySQL中查询和展示LONGBLOB类型数据的技巧总结》在MySQL中LONGBLOB是一种二进制大对象(BLOB)数据类型,用于存储大量的二进制数据,:本文主要介绍MySQL中查询和展示LO... 目录前言1. 查询 LONGBLOB 数据的大小2. 查询并展示 LONGBLOB 数据2.1 转换为十

MyBatis的xml中字符串类型判空与非字符串类型判空处理方式(最新整理)

《MyBatis的xml中字符串类型判空与非字符串类型判空处理方式(最新整理)》本文给大家介绍MyBatis的xml中字符串类型判空与非字符串类型判空处理方式,本文给大家介绍的非常详细,对大家的学习或... 目录完整 Hutool 写法版本对比优化为什么status变成Long?为什么 price 没事?怎

C#之枚举类型与随机数详解

《C#之枚举类型与随机数详解》文章讲解了枚举类型的定义与使用方法,包括在main外部声明枚举,用于表示游戏状态和周几状态,枚举值默认从0开始递增,也可手动设置初始值以生成随机数... 目录枚举类型1.定义枚举类型(main外)2.使用生成随机数总结枚举类型1.定义枚举类型(main外)enum 类型名字

Python lambda函数(匿名函数)、参数类型与递归全解析

《Pythonlambda函数(匿名函数)、参数类型与递归全解析》本文详解Python中lambda匿名函数、灵活参数类型和递归函数三大进阶特性,分别介绍其定义、应用场景及注意事项,助力编写简洁高效... 目录一、lambda 匿名函数:简洁的单行函数1. lambda 的定义与基本用法2. lambda

C语言自定义类型之联合和枚举解读

《C语言自定义类型之联合和枚举解读》联合体共享内存,大小由最大成员决定,遵循对齐规则;枚举类型列举可能值,提升可读性和类型安全性,两者在C语言中用于优化内存和程序效率... 目录一、联合体1.1 联合体类型的声明1.2 联合体的特点1.2.1 特点11.2.2 特点21.2.3 特点31.3 联合体的大小1

MySQL 索引简介及常见的索引类型有哪些

《MySQL索引简介及常见的索引类型有哪些》MySQL索引是加速数据检索的特殊结构,用于存储列值与位置信息,常见的索引类型包括:主键索引、唯一索引、普通索引、复合索引、全文索引和空间索引等,本文介绍... 目录什么是 mysql 的索引?常见的索引类型有哪些?总结性回答详细解释1. MySQL 索引的概念2

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符

Java获取当前时间String类型和Date类型方式

《Java获取当前时间String类型和Date类型方式》:本文主要介绍Java获取当前时间String类型和Date类型方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录Java获取当前时间String和Date类型String类型和Date类型输出结果总结Java获取