C++(第一天-----命名空间和引用)

一、C/C++的区别

1、与C相比
  c语言面向过程,c++面向对象。
  c++能够对函数进行重载,可使同名的函数功能变得更加强大。
  c++引入了名字空间,可以使定义的变量名更多。
  c++可以使用引用传参,引用传参比起指针传参更加快,指针传参还需要传送,而引用传参不需要传送参数,就能使函数共用一个变量。
  c++使用了类,能够继承,继承使得定义相似的类时能够直接从上一层得到一些方法或变量来进行直接使用。
  c++相比C语言功能强大的同时,也带来了更复杂多样的语法,这对于初学者来说是一个大的难点,这也使得c++在编程和学习上的难度提高了,并且c++的效率仍然不如C语言,c语言适合底层开发,c++适合c/s的软件开发. c/s — client /server。
2、C的扩展
C++是在C语言的基础上扩展而来,所以C++ 完全兼容C语言,可以在C++程序中写C语言的代码。

二、在c++中使用c语言库函数

extern "C"{//标准C库函数的头文件#include<stdio.h>//自定义的第三方C库头文件//也就是你使用的C编译器编译好的库对应的头文件#include "add.h"
}

例子:编译一个动态库 libadd.so

gcc -fpic -shared add.c  -o  libadd.so 

extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言的方式进行编译,而不是C++的。

c++标准的头文件不带.h

三、命名/名字/名称空间 namespace

1、问题的引入
探讨:在实际的系统开发中,所有的开发工作,通常都不会仅由一个人来开发完成,不同的人只负责自己功能模块,他们在设计时,比如声明变量,通常情况下,不会考虑其他人是否已使用该变量名,在模块功能测试时,相互之间是独立的,完全没有问题,当系统功能合成 时,不可避免地会出现变量或函数的命名冲突,因为变量或函数重名而导致的问题将会造成一定的混乱。所以如何在同一个.cpp文件中定义相同变量名的两个全局变量呢

#include<iostream>int val = 200;
int val = 300;int main()
{return 0;
}

现象:编译会报错
解决方法:使用命名空间区分这两个全局变量
在这里插入图片描述
2、概念
其实命名空间就是类似一个黑盒子
3、作用
防止名字冲突
4、格式

namespace 命名空间名字
{//声明定义变量//声明定义函数//定义结构体/共用体/枚举 数据类型//声明类  定义对象
}

5、使用命名空间中的成员
1)using编译指令( 引进整个命名空间) —将这个盒子全部打开

 using namespace 命名空间名字;

2)using声明使特定的标识符可用(引进命名空间的某个成员) —将这个盒子中某个成员的位置打开

using 命名空间名字::成员名;

3)调用的时候指定是哪一个命名空间下的成员

cout<<命名空间名字::成员名

6、实例

#include<iostream>using namespace std;//使用名称空间LcdSpace   -501老王
namespace LcdSpace{int x = 10;int y = 20;typedef struct{int data;}Data_t;enum {LCD_COLOR_RED,LCD_COLOR_GREEN};int lcd_init(){return 0;}}; 
//使用名称空间TouchSpace -502老王
namespace TouchSpace{int x = 100;int y = 200;
};//外部的全局变量   --老外
//int x = 1000;
//int y = 2000;//2)使用using声明的方式去引入名字空间中的某个成员
//把这个TouchSpace黑盒子 打开一个角落,正好把某个成员放出来
//格式:using 命名空间名字::成员名;
//using  TouchSpace::x;void test01()
{using namespace LcdSpace;cout<<"x:"<<x<<" y:"<<y<<endl;
}int main()
{//3)使用using编译指令的方式 打开整个名字空间 using namespace TouchSpace;//如何使用名字空间里面的成员//1)使用 作用域限定符:: 去指定//格式:  名字空间的名字::成员变量名std::cout<<TouchSpace::x<<" "<<TouchSpace::y<<std::endl;std::cout<<x<<" "<<y<<std::endl;std::cout<<LcdSpace::x<<" "<<LcdSpace::y<<std::endl;LcdSpace::Data_t data;LcdSpace::lcd_init();//我们有时候为了强调该变量的全局特性,可以在前面加上::修饰cout<<x<<" "<<y<<endl;test01();return 0;
}

7、命名空间的嵌套

namespace myspace{int x=10;int y=20;namespace spaceA{int a=100;void setValue(int data){a = data;}void printValue(){std::cout<<"a:"<<a<<std::endl;}}
}
使用:
myspace::spaceA::printValue();

8、同名命名空间
命名空间可以分开定义,也就是说,你在定义一个命名空间之后,如果后面想要在这个命名空间里面再次添加某些数据成员或者函数成员,可以再次接着定义。

namespace myspace{int x=10;int y=20;
}
namespace myspace{int a=100;int b=200;void print(){std::cout<<"x:"<<x<<" y:"<<y<<std::endl;}
}

9、匿名命名空间

namespace {int data=123;
}

可以在本文件中直接使用data, 限制空间中的成员只能在本文件中使用,类似c语言中的static修饰

10、全局作用域
全局作用域是从C语言就开始有的一种作用域,在C++中,有时为了强调某符号的全局特性,或为了避免与导入的名字空间中的重名符号冲突,会在使用全局符号的时候加上 作用域解析符

int global = 100;
int main()
{int global = 200;// 重名的标识符,外层的作用域会被内层的掩盖cout <<   global << endl; // 输出200// 使用双冒号引用全局作用域中的标识符cout << ::global << endl; // 输出100
}

1.全局作用域的名字空间是匿名的,引用全局作用域符号只需加 :: 即可。
2.名字空间的本质就是作用域,遵守C语言关于作用域的基本原则,如内层作用域重名符号会掩盖外层作用域的重名符号。

四、引用

1、问题的引入

//值传递
int swap1(int a,int b)
{a = a+b;b = a-b;a = a-b;    
}
//地址传递
int swap2(int *pa,int *pb)
{int temp = *pa;*pa = *pb;*pb = temp;
}
int  main()
{int aa = 100;int bb = 200;swap1(aa,bb);//值传递swap2(&aa,&bb);//地址传递
}

问题:值传递书写方式简单,但是不能修改变量所在内存空间的数据;地址传递能够修改变量所在内存空间的数据,但是需要复杂的解引用写法,而且使用过程中可能出现问题(空指针,不合法内存),导致程序不安全。
有没有一种方法:集中两者的优点呢,也就是说,既能够书写简单,同时也能修改内存空间的数据,提高程序的安全性!
解决方法:使用C++中的引用。
2、概念
引用就是一个变量或者是常量的别名,对引用的操作与对变量直接操作完全一样。引用是一种关系型声明的类型,说明它跟别的变量的关系,它所声明的变量不占内存空间,通俗来讲,是已有变量的别名,来说明跟已有变量的关系,所以引用变量的类型要跟已有变量的类型保持一致。
在这里插入图片描述
3.定义格式
以前的指针:数据类型 * 指针名 = &变量
现在的引用:数据类型 & 引用名 = 变量(数据类型必须与变量类型一致,而且必须要初始化)

int a = 100;
//给变量a起一个别名(定义引用)
//int 表示引用变量的数据类型,ra表示给变量a起的小名字就叫做ra
int &ra = a;
char *str = "hello";
char*(&rs) = str;//给指针变量str定义一个引用rs//给常量10起一个别名,给常量起一个别名必须在定义引用的时候加const 修饰
const int &rval = 10;

5.引用特点

  • &在定义的时候不是取地址运算符,而是起标识作用,表示给某个变量或者常量起一个别名,所以引用不是变量。
  • 在定义引用的时候,数据类型指的是 目标变量或者常量的数据类型。
  • 定义引用的时候,必须同时对其进行初始化。
  • 引用定义完毕后,相当于目标变量有两个名称,也就是目标原变量名和引用名,直接使用引用名就相当于直接操作该目标变量对应的内存空间。
  • 引用定义完毕后,不能 再把该引用名作为其他变量名的别名
  • 引用本身不占存储单元,仅仅是作为变量的别名。对引用求地址,就是对目标变量求地址。&ra与&a相等。
  • 不能建立引用的数组。因为数组是一个由若干个元素所组成的集合,所以无法建立一个由引用组成的集合,但是可以建立数组的引用。
const int &arr[3]={1,2,3}; 引用的数组----错误    [] 优先级 大于 &
int n[3] = {2, 4, 6};
int (&rn)[3] = n;     //数组的引用
  • 如果引用的对象是常量,那么引用必须用const修饰
int a = 100;
int b = 200;
//给变量a起一个别名(定义引用)
int &ra = a;
ra = b;//将变量b的值赋值给变量a所在的内存空间
cout<<"a:"<<a<<endl;
//引用取地址与变量取地址相等
cout<<"&a:"<<&a<<" &ra:"<<&ra<<endl;
//给常量10起一个别名
const int &rval = 10;

6.引用与常量

  • 将一个引用设置为常量后,不能通过该引用修改数据,但仍可通过被引用的变量来改变
int a = 100;
const int & b = a;//b和a是同一内存,但不能直接修改b
b = 1000;//错误
a = 1000;//正确

被引用的数据是常量,引用本身也必须是常量:

const int a = 100;
const int &b = a;//OK
int &b = a;//error
int &ra = 10;//error
const &ra = 10;//OK

7.引用的应用

  • 引用作为参数(值, 地址, 引用)
    引用的一个重要作用就是作为函数的参数。C语言阶段 如果在某个函数中想要改变另一个函数的变量,则需要进行地址传递,现在C++阶段又新增了一个引用传递,同样也能在一个函数中修改另一个函数的变量。
int func(int &ra,int &rb)
{ra = ra + rb;rb = ra - rb;ra = ra - rb;
}
//如果仅仅是访问变量的数据而不做修改,可以设置为常引用,达到引用的安全性
//常引用不能通过引用修改目标变量的值,
int print(const int &ra,const int &rb)
{cout<<ra<<" "<<rb<<endl;
}
int main()
{int a = 10;int b = 20;func(a,b); // func(10,20); 错误 ,因为该函数定义的参数不是常引用print(a,b); 
}
  • 引用作为函数返回值
    格式:
返回值数据类型 &函数名(形参列表及类型说明)
{

特点:
a. 以引用的形式返回函数值,定义函数时需要在函数名前加&
b. 用引用返回一个函数值的最大好处是,在内存中不产生被返回值 的副本。

#include <iostream>
using namespace std;int g_a; // 定义全局变量g_aint& test() {g_a = 168;return g_a;
}int main()
{//左值变量i 是直接从变量g_a中拷贝int i = test();cout << i << endl; return 0;
}

c. 不能返回局部变量的引用 ,因为局部变量在函数调用结束之后内存空间就被释放了

char*& initMem(int size)
{char *p = new char[size];return p;
}
int main()
{//会发生段错误,不能返回局部变量的引用char*(&p) = initMem(1024);strcpy(p,"hello");
}
正确写法:把initMem函数的p指针改为全局变量或者静态变量
char*& initMem(int size)
{static char *p = new char[size];return p;
}

d. 如果一个函数的返回值是一个引用,那么函数可以调用可以作为=的左值

test() = 100;
int val=100;int& getData()
{return val;
}
int main()
{getData() = 200;cout<<"val:"<<val<<endl;}

8.总结
引用传递的性质像指针传递,书写形式像值传递
如果只需要借用一下别名,就没必要要用指针
练习1:求下面的结果

#include <iostream> 
using namespace std; 
int f(int i){ return ++i; } 
int& g(int &i){ return ++i; } 
int h(int i){ return ++i; } 
int main() 
{ int a = 0, b = 0, c = 0; a += f(g(a)); b += g(g(b)); c += f(h(c)); cout << "a=" << a << ",b=" << b << ",c=" << c << endl; return 0;  
}

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

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

相关文章

基于YOLOv9+pyside的安检仪x光危险物物品检测(有ui)

安全检查在公共场所确保人身安全的关键环节&#xff0c;不可或缺。X光安检机作为必要工具&#xff0c;在此过程中发挥着重要作用。然而&#xff0c;其依赖人工监控和判断成像的特性限制了其应用效能。本文以此为出发点&#xff0c;探索了基于Torch框架的YOLO算法在安检X光图像中…

Xcode安装Simulator失败问题解决方法

Xcode安装Simulator_Runtime失败&#xff0c;安装包离线安装保姆级教程 Xcode更新之后有时候会提示要安装模拟器运行时环境&#xff0c;但是用Xcode更新会因为网络原因&#xff0c;我觉得基本上就是因为苹果服务器的连接不稳定导致的&#xff0c;更可气的是不支持断点续…

【论文阅读】--Popup-Plots: Warping Temporal Data Visualization

弹出图&#xff1a;扭曲时态数据可视化 摘要1 引言2 相关工作3 弹出图3.1 椭球模型3.1.1 水平轨迹3.1.2 垂直轨迹3.1.3 组合轨迹 3.2 视觉映射与交互 4 实施5 结果6 评估7 讨论8 结论和未来工作致谢参考文献 期刊: IEEE Trans. Vis. Comput. Graph.&#xff08;发表日期: 2019&…

DICOM灰度图像、彩色图像的窗宽、窗位与像素的最大最小值的换算关系?

图像可以调整窗宽、窗位 dicom图像中灰度图像可以调整窗宽、窗位&#xff0c;RGB图像调整亮度或对比度&#xff1f;_灰度 图 调节窗宽-CSDN博客 窗宽、窗位与像素的最大最小值的换算关系? 换算公式 max-minWindowWidth; (maxmin)/2WindowCenter; 详细解释 窗宽&#xff0…

视频太大怎么压缩变小?6款视频压缩软件免费版分享

视频太大怎么压缩得又小又清晰呢&#xff1f;无论是视频文件传输、视频文件存储&#xff0c;还是进行自媒体视频上传&#xff0c;都对视频文件的大小有一定的限制。高质量的视频文件往往伴随着文件占据大量存储空间&#xff0c;导致文件传输速度变慢。今天教大家6种视频压缩软件…

试用笔记之-汇通来电显示软件

首先汇通来电显示软件下载 http://www.htsoft.com.cn/download/httelephone.rar

IP白名单及其作用解析

在网络安全领域&#xff0c;IP白名单是一项至关重要的策略&#xff0c;它允许特定的IP地址或地址范围访问网络资源&#xff0c;从而确保只有受信任的终端能够连接。下面&#xff0c;我们将深入探讨IP白名单的定义、作用以及实施时的关键考虑因素。 一、IP白名单的定义 IP白名单…

深度学习21-30

1.池化层作用&#xff08;筛选、过滤、压缩&#xff09; h和w变为原来的1/2&#xff0c;64是特征图个数保持不变。 每个位置把最大的数字取出来 用滑动窗口把最大的数值拿出来&#xff0c;把44变成22 2.卷积神经网络 &#xff08;1&#xff09;conv&#xff1a;卷积进行特征…

stm32学习笔记---USART串口协议(理论部分)

目录 通信 通信的目的 通信协议 STM32的通信协议 各种协议的通信引脚介绍 通信空间和时间 时钟特性 电平特性 设备特性 串口通信 硬件电路 电平标准 串口参数及时序 时序 串口的参数 串口通信的实际波形 声明&#xff1a;本专栏是本人跟着B站江科大的视频的学习…

Vue 项目部署为 HTTPS 站点

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;爱蹦跶的大A阿 &#x1f525;当前正在更新专栏&#xff1a;《JavaScript保姆级教程》、《VUE》、《Krpano》 ✨ 前言 在将 Vue 项目部署为 HTTPS 站点时&#xff0c;你需要配置 HTTPS 证书和服务器。以下是一个基本的步骤和…

深入解析 androidx.databinding.BaseObservable

在现代 Android 开发中&#xff0c;数据绑定 (Data Binding) 是一个重要的技术&#xff0c;它简化了 UI 和数据之间的交互。在数据绑定框架中&#xff0c;androidx.databinding.BaseObservable 是一个关键类&#xff0c;用于实现可观察的数据模型。本文将详细介绍 BaseObservab…

java 代码块

Java中的代码块主要有三种类型&#xff1a;普通代码块、静态代码块、构造代码块。它们的用途和执行时机各不相同。 普通代码块&#xff1a;在方法内部定义&#xff0c;使用一对大括号{}包围的代码片段。它的作用域限定在大括号内&#xff0c;每当程序执行到该代码块时就会执行其…

Pikachu 不安全的文件下载(Unsafe file download)概述 附漏洞利用案例

目录 获取下载链接 修改链接 重新构造链接 拓展 不安全的文件下载概述 文件下载功能在很多web系统上都会出现&#xff0c;一般我们当点击下载链接&#xff0c;便会向后台发送一个下载请求&#xff0c;一般这个请求会包含一个需要下载的文件名称&#xff0c;后台在收到请求…

初识Java(复习版)

一. 什么是Java Java是一种面向对象的编程语言&#xff0c;和C语言有所不同&#xff0c;C语言是一门面向过程的语言。偏底层实现&#xff0c;比较注重底层的逻辑实现。不能一味的说某一种语言特别好&#xff0c;每一种语言都是在特定的情况下有自己的优势。 二.Java语言发展史…

Docker Compose 一键快速部署 RocketMQ

Apache RocketMQ是一个开源的分布式消息中间件系统&#xff0c;最初由阿里巴巴开发并贡献给Apache软件基金会。RocketMQ提供了高性能、高可靠性、高扩展性和低延迟的消息传递服务&#xff0c;适用于构建大规模分布式系统中的消息通信和数据同步。 RocketMQ支持多种消息模型&am…

武汉星起航:无锡跨境电商加速“出海”,物流升级助品牌全球布局

随着全球化的不断深入&#xff0c;跨境电商作为数字外贸的新业态&#xff0c;正逐渐成为无锡企业拓展海外市场的重要渠道。武汉星起航关注到&#xff0c;近年来&#xff0c;无锡市通过积极推进国际物流枢纽建设&#xff0c;完善海外仓布局&#xff0c;以及各特色产业带的积极参…

JavaMySQL 学习(基础)

目录 Java CMD Java发展 计算机存储规则 Java学习 switch新用法&#xff08;可以当做if来使用&#xff09; 数组定义 随机数 Java内存分配 MySQL MySQL概述 启动和停止 客户端连接 数据模型 关系型数据库 SQL SQL通用语法 SQL分类 DDL--数据定义语言 数据库…

Intellij Idea显示回退和前进按钮的方法

方法1 使用快捷键&#xff1a; 回到上一步 ctrl alt <-&#xff08;左方向键&#xff09;回到下一步 ctrl alt ->&#xff08;右方向键&#xff09; 方法2&#xff1a; Preferences -> Appearance & Behavior -> Menus and Toolbars -> Navigation B…

SEO与AI的结合:如何用ChatGPT生成符合搜索引擎优化的内容

在当今数字时代&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;已成为每个网站和内容创作者都必须掌握的一项技能。SEO的主要目标是通过优化内容&#xff0c;使其在搜索引擎结果页面&#xff08;SERP&#xff09;中排名更高&#xff0c;从而吸引更多的流量。然而&#xf…

如何养成爱自己的习惯:吸引世间美好,改变命运

在这个快节奏、高压力的时代&#xff0c;我们常常被各种事务所困扰&#xff0c;内心难以得到真正的宁静。然而&#xff0c;古老的智慧告诉我们&#xff0c;“静”是宇宙万物的根源&#xff0c;是生命恢复的根本。本文将探讨如何养成“静”的习惯&#xff0c;从而吸引世间美好&a…