cpp_03_引用_类型转换_温和强转_面向对象

1  引用的应用

1.1  数据传递--值传递

        C语言只要涉及数据传递(例如:初始化、赋值、传参、返回值),

        都为值传递(将数据复制一份给到目标内存)。

// value.cpp 值传递:将数据复制一份给别人
#include <iostream>
using namespace std;void foo( int x ) {  }int bar( ) {int m = 8888;return m;
}int main( void ) {int a = 10; // 初始化a = 20; // 赋值foo( a ); // 传参/*|8888|*/bar( ); // 返回值return 0;
}

        C++语言因为有引用,可以不做值传递。 

        1)引用型形参:函数的形参是实参的别名,避免对象复制的开销。

                非常引用型参数,可在函数中修改实参值;

                引用型参数,防止了对实参的意外修改,  也接受常量型实参(右值)。

// vparam.cpp 引用 作为函数的 形参
// 当我们在设计一个函数时,只要可以确定在函数内部绝对不修改实参,那么大胆的加上const
#include <iostream>
using namespace std;void Swap( int* x, int* y ) { // int z = *x;*x = *y;*y = z;
}void Swap( int& x, int& y ) { // 非常引用型 形参:函数内部可以直接修改实参int z = x;x = y;y = z;
}
void Printer( const int& x, const int& y ) { // 常引用型 形参:能够防止意外修改实参
//  x = 888; // 编译器会提醒我们read-only  (打印机就应该原样打印哦)cout << x << ' ' << y << endl;
}int main( void ) {int a=10, b=20;Swap( a, b );
//  Swap( &a, &b ); // 这种写法并不直观cout << "a=" << a << ", b=" << b << endl;Print( a, b );Print( 888, 999 ); //接受常亮型实参(右值)return 0;
}

         2)引用型的返回值:从函数中返回引用,一定要保证函数返回后,该引用的目标依然有效

                        -可以返回全局静态变量的引用

                        -可以返回在中动态创建(new)的对象的引用

                        -可以返回引用型参数本身

                        -可以返回成员变量的引用 

                        -可以返回调用对象自身的引用 

                        -不能返回局部变量的引用

               非常引用型返回值:通过引用可以修改目标

               引用型返回值:通过引用不能修改目标

// vreturn.cpp 引用 作为函数的 返回值
#include <iostream>
using namespace std;
int g_value = 0;
int& foo() { // 非常引用型 返回值:可以通过引用修改目标return g_value;
}
const int& fooo() { // 常引用型 返回值:不可以通过引用修改目标return g_value;
}int& bar() {static int s_value=0;//这行代码是在程序启动时就执行,而且只执行1次,不是每次调bar都执行cout << "s_value=" << s_value << endl;return s_value;
}int& hum() {int* p = new int;return *p;
}int& fun( int& x ) {// ...return x; // 返回 引用型 参数本身
}
/*
int& boo() {int m = 666;return m; // 不要返回局部变量的引用
}
*/
int main( void ) {foo() = 100;cout << "g_value=" << g_value << endl;//    fooo() = 888; // readonly - errorbar() = 200;bar();hum() = 300;int a_value = 0;fun(a_value) = 400;cout << "a_value=" << a_value << endl;//  boo();return 0;
}

        在实现(汇编)层面,引用就是指针,但在C++语言层面,引用不是实体类型,由此推导出,C++语言层面,引用与指针存在明显的差别:

        1)指针可以不初始化,其目标可在初始化后随意变更(指针常量除外),

              引用必须初始化,且一旦初始化就无法变更其目标。

        2)存在空指针,不存在空引用

        3)存在指向指针的指针,不存在引用的引用

        4)存在指针的引用,不存在引用的指针

        5)存在指针数组,不存在引用数组,但存在数组引用。

// poi_ref 指针 和 引用 的差别
#include <iostream>
using namespace std;int main( void ) {int a=10, b=20;int* pa = &a; // 指针可以不做初始化,也可以做初始化pa = &b; // 指针可以随意变更它所指向的目标内存int& ra = a; // 引用必须初始化ra = b; // 引用不可以随意变更它所代表的目标内存( ra仍然是a的别名 )pa = NULL; // 存在空指针
//  ra = NULL; // 不存在空引用int** ppa = &pa; // 存在二级指针
//  int&& rra = ra;  // 不存在二级引用int* &rpa = pa; // 存在指针的引用  !!
//  int& *pra = &ra; // 不存在引用的指针int* p = &ra; // 这里取的并不是引用本身的地址,而是引用的目标内存a的地址int x, y, z;int*parr[3] = {&x, &y, &z}; // 存在指针的数组
//  int&rarr[3] = {x,y,z}; // 不存在引用的数组int arr[3];int(&rr)[3] = arr; // 存在数组的引用return 0;
}

 

2  显示类型转换(强转)

        C风格的显示类型转换:        (int)a 

        C++风格的显示类型转换:    int(a) 

// convert_pre.cpp 显式(强制)类型转换
#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;pv = &b;pv = &c;pv = &d;pv = &e;// void* 到 任何其他类型的指针 都必须强转(显式转换)int* pa = (int*)(pv);double* pb = (double*)(pv);float* pc = (float*)(pv);short* pd = (short*)(pv);char* pe = (char*)(pv);// 任何类型的 非常指针 到 同类型的常指针 都可以隐式转换const int* cpa = pa;const double* cpb = pb;const float* cpc = pc;const short* cpd = pd;const char* cpe = pe;// 任何类型的 常指针 到 同类型非常指针 都必须强转pa = (int*)(cpa);pb = (double*)(cpb);pc = (float*)(cpc);pd = (short*)(cpd);pe = (char*)(cpe);return 0;
}

3  温和强转

3.1  静态类型转换

                static_cast<目标类型>(源类型变量)

                隐式类型转换的逆转换(去常除外)

                自定义类型转换 

3.2  动态类型转换 

                dynamic_cast<目标类型>(源类型变量) 

                多态父子类指针或引用之间的转换 

3.3  常类型转换

                const_cast<目标类型>(源类型变量)

                去除指针或引用上的const属性

3.4  重解释类型转换

                reinterpret_cast<目标类型>(源类型变量)

                任意类型的指针之间的转换

                任意类型的引用之间的转换

                任意类型的指针和整型之间的转换

// convert.cpp 显式(强制)类型转换
#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*外,其他任何类型的指针之间都必须强转*************pa = reinterpret_cast<int*>(pb); // double*-->int*pb = reinterpret_cast<double*>(1000); // int-->double*return 0;
}

 

4  面向对象

4.1  what

        一切皆对象。

        把大型软件看成是由多个对象组成的团推。

        对象拥有足够的智能,能够理解来自其他对象的信息,并以适当的行为作出反应。

        面向对象的三大特征:封装、继承、多态。

4.2  why

        相比分而治之的结构化程序设计,强调大处着眼的面向对象程序设计思想,更适合开发大型软件。

        得益于代码复用等面向对象的固有特征,软件开发的效率获得极大提升,成本却大幅降低。

4.3  how

        至少掌握一种面向对象的程序设计语言,如C++

        深入理解封装、继承、多态等面向对象的重要概念

        学习设计模式,源自多年成功经验的积累总结。

第三个错误:等号右边是右值,故等号左边应为万能引用int* const &r :

//test.cpp
#include <iostream>
using namespace std;int main( void ) {int arr[9] = {9,3,1,4,2,7,5,8,6};int* p = arr;       // 正确  &arr[0]int(*pp)[9] = &arr; // 正确//  int* &r = arr;      // 错误 &arr[0]     int* const& r = arr;// 正确int(&rr)[9] = arr;  // 正确
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/229410.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

删除远端消息, 重进会话仍然取回已删除的消息

用户调用删除函数, 服务器不会判断 对应的 sentTime 是否存在, 仅仅是使用sentTime 直接进行消息删除, 然后返回操作成功; 用户删除远端消息时, 需要保证sentTime的合法性 - (void)deleteRemoteMessage:(RCConversationType)conversationType targetId:(NSString *)targetId me…

Diva配置——Communication Tests

关联文章:CANoe.Diva生成测试用例 Diva目录 一、CANoe.Diva简介二、Communication Tests配置一、CANoe.Diva简介 CANoe.DiVa 是一种 CANoe 选项,用于对 ECU 中的诊断软件实施进行自动化测试。 可以通过CANdelaStudio制作的CDD或ODX文件,经过Diva配置自动生成测试用例和测试脚…

用XPath爬取Crossin教室的文章列表页信息示例

一、背景&#xff1a; 2023.12.12,经过本人的多日权衡比较&#xff0c;我决定购买了crossin老师的Python服务。主要实现了能够通过其编程教室提供的答疑群平台答疑解惑。基于其答疑服务感觉还是不错的。同时能够逐步扎实Python基础与爬虫等相关的技术。今日用xpath完成了一个爬…

jetson nano 编译出现/usr/bin/ld: cannot find -lcudart

问题描述 jetson nano 编译出现/usr/bin/ld: cannot find -lcudart 问题分析 在 Jetson Nano 上编译时遇到 /usr/bin/ld: cannot find -lcudart 错误&#xff0c;表示编译器无法找到名为 libcudart 的 CUDA 运行时库。 CMakeLists.txt 里面添加库路径。 解决办法 要解决这…

【日积月累】Mysql性能优化

目录 【日积月累】Mysql性能优化 1.前言2.MySql性能优化的主要方面2.1硬件和操作系统成面优化2.2架构设计层优化&#xff08;表结构&#xff09;2.3程序配置优化2.5表结构及索引优化2.4sql执行优化 3.总结4.参考 文章所属专区 积月累 1.前言 MySQL是一种常用的开源关系型数据…

33 动态规划和递归求解不同路径II

问题描述&#xff1a;一个机器人位于一个mn网格的左上角(起始点在下图中标记为Start)&#xff0c;机器人每次只能向下或者向右移动一步&#xff0c;机器人试图到达网格的右下角&#xff0c;机器人试图到达网格的右下角&#xff0c;现在考虑网格中有障碍物&#xff0c;那么从左上…

第2章 线性结构

一、选择题 1. 顺序存储结构的优点是&#xff08; A &#xff09; A&#xff0e;存储密度大 B&#xff0e;插入运算方便 C&#xff0e;删除运算方便 D&#xff0e;可用于各种逻辑结构的存储表示 2. 下面关于线性表的叙述中&#xff0c;错误的是&#xff08; B…

ACL原理和配置

一.ACL概述 1.介绍 ACL 访问控制列表&#xff0c;可以通过对网络中报文流的精确识别&#xff0c;与其他技术结合&#xff0c;达到控制网络访问行为、防止网络攻击和提高网络带宽利用率的目的&#xff0c;从而切实保障网络环境的安全性和网络服务质量的可靠性。 2.概述 ACL是…

ShenYu网关注册中心之Zookeeper注册原理

文章目录 1、客户端注册流程1.1、读取配置1.1.1、用于注册的 ZookeeperClientRegisterRepository1.1.2、用于扫描构建 元数据 和 URI 的 SpringMvcClientEventListener 1.2、扫描注解&#xff0c;注册元数据和URI1.2.1、构建URI并写入Disruptor1.2.2、构建元数据并写入Disrupto…

[C语言]大小端及整形输出问题

假设在一个32位little endian 的机器上运行下面的程序&#xff0c;结果是多少 ? 1.1先看以下三个程序 #include <stdio.h> int main() {long long a 1, b 2, c 3;printf("%lld %lld %lld\n", a, b, c); // 1 2 3printf("%d %d %d %d %d %d\n&quo…

LeetCode第376场周赛

文章目录 1.Find Missing and Repeated Values2.Divide Array Into Arrays With Max Difference3.Minimum Cost to Make Array Equalindromic 1.Find Missing and Repeated Values 直接暴力过 class Solution { public:vector<int> findMissingAndRepeatedValues(vecto…

Learning Semantic-Aware Knowledge Guidance forLow-Light Image Enhancement

微光图像增强&#xff08;LLIE&#xff09;研究如何提高照明并生成正常光图像。现有的大多数方法都是通过全局和统一的方式来改善低光图像&#xff0c;而不考虑不同区域的语义信息。如果没有语义先验&#xff0c;网络可能很容易偏离区域的原始颜色。为了解决这个问题&#xff0…

c语言-全局变量与局部变量

目录 1、&#xff08;作用&#xff09;域的概念 2、全局与局部的相对性 3、生命周期 3、静态变量static 结语&#xff1a; 前言&#xff1a; 在c语言中&#xff0c;全局变量的可见范围是整个工程&#xff0c;而局部变量的可见范围从该变量被定义到该作用域结束&#xff0c…

JavaScript装饰者模式

JavaScript装饰者模式 1 什么是装饰者模式2 模拟装饰者模式3 JavaScript的装饰者4 装饰函数5 AOP装饰函数6 示例&#xff1a;数据统计上报 1 什么是装饰者模式 在程序开发中&#xff0c;许多时候都我们并不希望某个类天生就非常庞大&#xff0c;一次性包含许多职责。那么我们就…

【JavaEE】多线程(5) -- 阻塞队列

目录 1.阻塞队列是什么? 2.生产者消费者模型 3.标准库中的阻塞队列 4.阻塞队列的实现 1.阻塞队列是什么? 阻塞队列是⼀种特殊的队列. 也遵守 "先进先出" 的原则 阻塞队列能是⼀种线程安全的数据结构, 并且具有以下特性: 当队列满的时候, 继续⼊队列就会阻塞, …

I/O流的相关内容

首先我们了解一下什么是文件&#xff1a; 文件其实就是让我们用来保存数据的地方&#xff0c;它可以用来保存信息&#xff0c;图片&#xff0c;以及音频等各类数据。 文件流&#xff1a; 那我们是如何通过我们的程序来进行对文件的操作呢&#xff1f;这里我们就要提出一个概…

wpf将静态变量绑定到控件属性

有时候需要将后台一个静态属性绑定到xaml前台&#xff0c;经过实践&#xff0c;有如下两种绑定的方式 例如后台声明一个类&#xff0c;类中包含静态变量&#xff1a; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T…

Crow:Middlewares 庖丁解牛2 产生序列

include\crow\utility.h内有这样一段比较晦涩难懂的代码: template<class T> using Invoke = typename T::type;template<unsigned...> struct seq {using type = seq; };template<class S1, class S2> struct concat;template<unsigned... I1, unsigne…

2023年金属非金属矿山(地下矿山)安全管理人员证模拟考试题库及金属非金属矿山(地下矿山)安全管理人员理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年金属非金属矿山&#xff08;地下矿山&#xff09;安全管理人员证模拟考试题库及金属非金属矿山&#xff08;地下矿山&#xff09;安全管理人员理论考试试题是由安全生产模拟考试一点通提供&#xff0c;金属非金…

【linux--进程通信之共享内存】

目录 一、共享内存的原理二、共享内存的数据结构三、共享内存使用的函数2.1ftok函数2.2shmget函数2.3shmctr函数2.4shmat函数2.5shmdt函数 四、实现进程通信 一、共享内存的原理 共享内存实际是操作系统在实际物理内存中开辟的一段内存。 共享内存实现进程间通信&#xff0c;是…