引用和类型强转

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

相关文章

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

Mysql BLOB类型介绍

BLOB类型的字段用于存储二进制数据 在MySQL中,BLOB类型,包括:TinyBlob、Blob、MediumBlob、LongBlob,这几个类型之间的唯一区别是在存储的大小不同。 TinyBlob 最大 255 Blob 最大 65K MediumBlob 最大 16M LongBlob 最大 4G

Oracle type (自定义类型的使用)

oracle - type   type定义: oracle中自定义数据类型 oracle中有基本的数据类型,如number,varchar2,date,numeric,float....但有时候我们需要特殊的格式, 如将name定义为(firstname,lastname)的形式,我们想把这个作为一个表的一列看待,这时候就要我们自己定义一个数据类型 格式 :create or repla

MyBatis 切换不同的类型数据库方案

下属案例例当前结合SpringBoot 配置进行讲解。 背景: 实现一个工程里面在部署阶段支持切换不同类型数据库支持。 方案一 数据源配置 关键代码(是什么数据库,该怎么配就怎么配) spring:datasource:name: test# 使用druid数据源type: com.alibaba.druid.pool.DruidDataSource# @需要修改 数据库连接及驱动u

按揭贷款类型

按揭贷款可以根据不同的分类标准分为多种类型。以下是按揭贷款的一些常见分类: 按贷款利率分类: 固定利率按揭(Fixed Rate Mortgage, FRM):在整个贷款期间,利率保持不变,这意味着每月还款额也是固定的。浮动利率按揭(Adjustable Rate Mortgage, ARM):贷款利率随市场利率的变化而调整,通常有一个基准利率加上一定的浮动点数。 按还款方式分类: 等额本息(

JavaSE(十三)——函数式编程(Lambda表达式、方法引用、Stream流)

函数式编程 函数式编程 是 Java 8 引入的一个重要特性,它允许开发者以函数作为一等公民(first-class citizens)的方式编程,即函数可以作为参数传递给其他函数,也可以作为返回值。 这极大地提高了代码的可读性、可维护性和复用性。函数式编程的核心概念包括高阶函数、Lambda 表达式、函数式接口、流(Streams)和 Optional 类等。 函数式编程的核心是Lambda