C++学习之路,从0到精通的征途:入门基础

目录

一.C++的第一个程序

二.命名空间

1.namespace的价值

2.命名空间的定义

3.命名空间使用

三.C++的输入与输出

1.<iostream>

2.流

3.std(standard)

四.缺省参数 

1.缺省参数的定义

 2.全缺省/半缺省

3.声明与定义

​五.函数重载

1.参数个数不同

2.参数类型不同

3.参数类型顺序不同

函数返回值不同是否能作为重载条件?

带有缺省参数的函数能构成重载吗?

六.引用

1.引用的概念和定义

2.引用的特性  

2.1引用在定义是必须初始化

2.2一个变量可以有多个引用

2.3引用一旦引用一个实体,再不能引用其他实体 

3.引用的使用

3.1引用传参

3.2引用作返回值

4.const引用

5.指针和引用的关系

七.inline

 1.inline的定义与概念

2.inline的特性

3.inline与宏函数的比较

八.nullptr

九.总结 


一.C++的第一个程序

        第一个程序当然是“Hello World”,不过这里我们使用C++的语法进行实现。

        在实现前,我们创建的文件必须得是.cpp文件,编译器在识别后缀为.cpp后才会调用C++编译器,这里后缀改为.c文件是会报错的。

#include<iostream>
using namespace std;int main()
{cout << "Hello World" << endl;return 0;
}

运行结果:

        这里对于代码有疑问是正常的,接下来我们来逐一讲解。

二.命名空间

1.namespace的价值

        在C语言中如果一个声明的变量名刚好与其他变量名重复或者与函数名等重复,则会出现报错,例如下面这段代码:

#include<stdio.h>
#include<stdlib.h>int rand = 0;int main()
{printf("%d\n", rand);return 0;
}

报错片段:

        可以看到报错语句为重定义:以前的定义是函数。

        在这里我们期望rand是int类型,但rand是函数类型,这说明由于stdlib.h中rand()的存在,编译器将rand识别为了函数,在C语言中如果要解决这样的问题只能再取一个其他变量名,但在C++中我们可以用命名空间去解决命名冲突的问题。

2.命名空间的定义

        定义命名空间,需要用到关键字namespace,后面跟命名空间的名字,这里用mySpace举例,再跟一对大括号{},{}中可以定义命名空间的成员,成员可以是变量/函数/类型等。

代码演示:

namespace mySpace
{int rand = 0;int Add(int left, int right){return left + right;}struct Node{struct Node* next;int val;};
}

        namespace本质是定义一个域,在C语言中由于不用域中可以定义同名变量,namespace也类似与这种特性,namespace定义的域与全局域各自独立,其通过域隔离解决了同名冲突的问题,且命名空间不会影响变量的生命周期。

        命名空间只能定义在全局,同时namespace也可以嵌套定义。

代码演示:

namespace mySpace
{namespace s1{int rand = 0;int a = 1;}namespace s2{int rand = 10;int a = 11;}
}
	printf("%d\n", mySpace::s1::a);printf("%d\n", mySpace::s2::a);

        在调用的过程中,我们使用域作用限制符::,它能在编译时通过指定域的形式进行查找。

        如第一条printf语句,就是访问MySpace中命名空间s1中的整型变量a,打印值为1。

运行结果:

·        在项目目工程文件中,同名的namespace会认为是一个namespace不会冲突:

·        我们再定义一个头文件,并创建一个同名namespace。

        

        在包含头文件后可以看到,程序并未报错,并成功输出b的值,这说明编译器认为两个namespace并不冲突,为同一个命名空间。

3.命名空间使用

         编译器的查找规则为: 1.先局部再全局        2.指定域中查找

        所以如果直接查找命名空间中的变量名而并未指定,则会报错,参考下面程序:

        如果要正确使用命名空间中定义的变量/函数,有三种方式:

        1.运用域作用限制符,指定命名空间访问,项目中推荐使用。

        2.使用using将命名空间中某个频繁使用的变量/函数展开,项目中不推荐使用。

这样就可以让上面的程序不报错了,但由于将命名空间中的a展开,可能会有同名冲突的风险。
3.用using展开命名空间中的所有成员项目中不推荐,冲突风险大,日常练习时方便推荐使用。

三.C++的输入与输出

1.<iostream>

        C++中的输入与输出不再使用<stdio.h>,而是用<iostream>,iostream是Input Output Stream 的缩写,库中定义了标准的标准的输入输出对象,其中包含<iostream>也会间接包含<stdio.h>,所以也能使用printf和scanf,不同编译器可能会报错。

2.流

        std::cin 是 istream 类的对象,它主要面向窄字符(narrow characters (of type char))的标准输入流。

        std::cout 是 ostream 类的对象,它主要面向窄字符的标准输出流。

        std::endl 是⼀个函数,流插入输出时,相当于插入一个换行字符加刷新缓冲区。现在可以简单理解为换行符。  

        <<是流插入运算符,>>是流提取运算符。(C语言中用这两个运算符做位运算左移/右移)

示例:

        C++中的输入输出不再需要像C语言那样手动指定格式,流可以自动识别变量类型,也能更好的支持自定义类型的输入输出。

例如:

3.std(standard)

        C++的标准库放在一个为std的命名空间中,cout/cin/endl都属于标准库,所以需要通过命名空间std去使用他们。   

        与命名空间的使用方式相同:

        1.域作用操作符,指定命名空间访问

	std::cin >> a;std::cout << a << std::endl;

        2.using展开频繁使用的成员

#include<iostream>
using std::cout;
using std::endl;int main()
{int a = 0;std::cin >> a;cout << a << endl;return 0;
}

        3.using展开命名空间,项目中不推荐使用,推荐日常练习

using namespace std;

四.缺省参数 

1.缺省参数的定义

        缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值。调用该函数时,如果并未传输指定的实参,则直接采用缺省值,否则使用指定的实参,缺省参数分为全缺省和半缺省参数。(有些地方把缺省参数也叫默认参数)

如图:

 2.全缺省/半缺省

        全缺省就是所有形参给缺省值,示例:

        半缺省就是部分下形参给缺省值,示例:

        由于这里是半缺省,a没有缺省值,所以在调用函数时必须传至少一个参数。                

        同时C++规定半缺省参数必须从右往左依次连续缺省,不能间隔跳跃给缺省值。

报错片段:

        带有缺省参数的函数调用,传参时不可跳跃,必须从左到右依次给实参。

3.声明与定义

        带有缺省参数的函数在声明和定义分离时,不能同时给缺省参数,规定必须在声明中出现。

五.函数重载

        C++中支持在同一作用域下同名函数的出现,但必须这些函数的形参个数不同,形参类型不同,或形参类型顺序不同,这样可以让函数调用呈现多态行为,更加灵活。

1.参数个数不同

2.参数类型不同

3.参数类型顺序不同

函数返回值不同是否能作为重载条件?

        由于函数名和参数相同,在调用函数时无法根据返回值的不同来区分到底要调用哪个函数,所以会报错,显示函数f重定义

        所以函数返回值不同并不能作为重载条件。

带有缺省参数的函数能构成重载吗?

        可以看到报错语句为对重载函数的调用不明确,说明带有缺省参数的函数构成重载,但在函数调用时,编译器不知道调用的是哪个函数,存在歧义,所以会导致报错。

六.引用

1.引用的概念和定义

        引用不是定义一个新变量,而是给已有的变量取一个别名,编译器不会为引用变量开辟空间,引用变量与被引用的变量使用同一块内存空间。

类型& 引用别名 = 引用对象

	int a = 0;int& b = a;int& c = a;

        b,c是变量a的别名。这里引用符号&与取地址符号相同,根据用法区分即可。

    int& d = b;

        也可以给别名b取别名为d,所以d也是a的别名         

      由于b,c,d是a的别名,四者同用一块内存空间,在++d后,a,b,c,d的值全部自增一,并且从运行结果可以看出四个变量的地址相同,共用一块空间。 

2.引用的特性  

2.1引用在定义是必须初始化

2.2一个变量可以有多个引用

2.3引用一旦引用一个实体,再不能引用其他实体 

3.引用的使用

        引用在实际操作中主要用来作引用传参引用作返回值,从而减少拷贝,提高效率,在改变引用对象的同时改变被引用对象。

3.1引用传参

        引用传参指针传参类似,但理解和使用更加简单和方便,以Swap函数举例:

void Swap(int& x, int& y)
{int tmp = x;x = y;y = tmp;
}

运行结果:

        可以看到a,b交换了值,但与指针不同的是函数体里无需解引用操作,因为引用对象与被引用对象使用的是同一块内存空间,直接交换即可。

3.2引用作返回值

        为了更好的举例,在这里我们添加数据结构栈的头文件和源文件,代码详细参考:栈:数据结构中的“时间管理大师” 

        可以看到在让栈顶加10的操作中出现了报错,报错提示为StackTop(&st)不是左值,说明此时栈顶不可被修改,为右值

分析:

              

        在函数返回时,操作系统会将返回值储存在一个临时对象中,再将临时对象中的值返回,因为这个临时对象具有常性,所以栈顶不能被修改。那如何才能让这个操作合法呢?

        在这里我们将引用作返回值,并将参数优化为引用参数

// 获取栈顶元素 
STDataType& StackTop(Stack& ps)
{assert(ps._top > 0);return ps._a[ps._top - 1];
}

        此时函数栈帧销毁后,返回对象top并不是存在临时对象中,即函数栈帧销毁对返回其引用并无影响,故此时栈顶可修改。

        为了更深刻的理解引用作返回值的情况,再举一个示例:

        这里可以看到,虽然编译器并未报错,但是返回值并未加10,由于ret存在于函数栈帧中,出函数后,ret也销毁了,所以返回引用结果出现问题。

        对于引用返回,函数栈帧结束后,如果返回对象在函数栈帧中,返回引用就会出现问题,如果返回对象不在函数栈帧中,可以正常返回其引用。

4.const引用

        可以引用一个const对象,但引用也必须为const,对于普通对象也可以进行const引用,因为对象的访问权限在引用过程中只可以缩小,不能放大。

        在类型转换中的const引用:

        由于在类型转换时,操作系统会创建临时对象,临时对象具有常性,所以在转换时需要用const引用接收。

临时对象:

        所谓临时对象就是编译器需要⼀个空间暂存表达式的求值结果时临时创建的⼀个未命名的对象, C++中把这个未命名对象叫做临时对象

        临时对象在以下三种常用情况下会创建:

        1. 函数传值返回

        2.表达式运算

        3.类型转换

5.指针和引用的关系

        指针与引用在实践中相辅相成,在功能上有重叠性,但都有各自的特点,互相不可替代。

七.inline

 1.inline的定义与概念

        被inline修饰的函数叫做内联函数,在编译时C++编译器会在调用的地方展开内联函数,这样调用内联函数时就不需要创建函数栈帧了,提高了效率。

2.inline的特性

        inline适用于频繁调用的短小函数,对于递归函数,代码量较多的函数加上inline也会被编译器忽略。

        通过该段代码的汇编可以看到,在调用内联函数Swap时,并没有call指令,说明Swap函数在调用中已展开,根据右边的汇编代码可以进一步验证。

        inline不建议声明和定义分离到两个文件,分离会导致链接错误,因为inline被展开,就没有函数地址,链接时会报错。

3.inline与宏函数的比较

        先来看一段宏函数:

        对于这个宏函数,为了巩固理解,需要回答下面三个问题: 

        1.为什么要加分号?

        宏函数是在预处理时,将语句整体替换到调用处,如果加了分号,分号也会一并调换。

        2.为什么加外面的括号?

        宏函数在与其他式子作运算时需要考虑优先级的问题,加了外面的括号,保证宏函数优先级更高。

        3.为什么加里面的括号?

        a,b各自为一个表达式,加了里面的括号,保证表达式的优先运算。

        从这三个问题可以看出宏函数的实现很复杂,且很容易出错,不方便调试,所以C++中设计inline的目的就是为了替代宏函数,在提高效率的同时,更容易实现,不过与宏不同的是,inline的展开是在编译而不是预处理阶段,使其更容易调试。

八.nullptr

        NULL实际是一个,在传统的C头文件(stddef.h)中,可以看到如下代码:

#ifndef NULL#ifdef __cplusplus#define NULL 0#else#define NULL ((void *)0)#endif
#endif

        所以在C++中NULL可能会被定义为字面常量0,在下面这种情况下,与程序的初衷违背:

        这里func(NULL)的目的是调用func(int* ptr),但却由于NULL被定义成了数字常量0,调用成了func(int x),所以如果要调用func(int* ptr),还得对NULL强转类型:

        但强转类型只能让NULL强转一种类型,无法应对变量的多种类型,所以C++在这里引入了一个关键字:nullptr它可以转换成任意其他类型的指针类型。使用nullptr定义空指针可以避免类型转换的问题,因为nullptr只能被隐式地转换为指针类型,而不能被转换为整数类型。

示例:

九.总结 

        C++ 的这些基础内容,是踏上这门强大编程语言之旅的重要一步。从第一个程序的 “Hello, World!” 开始,我们逐步揭开了命名空间、输入输出、缺省参数、函数重载、引用、inline函数以及 nullptr 等关键概念的神秘面纱。这些知识相互关联,共同构成了 C++ 编程的基石。

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

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

相关文章

用低代码平台集成人工智能:无需专业开发也能实现智能化

引言&#xff1a;人工智能的普及与企业需求 随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;越来越多的企业开始意识到其在提升运营效率、优化客户体验和推动业务创新方面的巨大潜力。从智能客服到自动化决策支持&#xff0c;从数据分析到个性化推荐&#x…

【Git】linux搭建Gitea配置mysql数据库

WindowsServer搭建内网Gitea【中文更方便使用】 1. 安装Gitea # 下载 wget https://dl.gitea.io/gitea/1.23.5/gitea-1.23.5-linux-amd642. 创建用户 # 创建 gitea 用户 sudo adduser --system --shell /bin/bash --comment Git Version Control --create-home --home-dir /…

RLHF-GRPO

RLHF&#xff08;Reinforcement Learning fromHuman Feedback&#xff0c;人类反馈强化学习&#xff09; 目的&#xff1a;为了让大模型的输出更贴合人类的偏好&#xff0c;拟合有用真实无害的结果。 思维导图 方法对比 发布时间&#xff1a;最初是采用PPO&#xff0c;但是后…

PIPC:基于博世冰羚Iceoryx的功能安全增强型通信框架

ICEORYX: 博世在量产ADAS领域装配率长期占据市场前三的份额,他们对于如何将自动驾驶数据高效流转的需求更为迫切,为此在大神Michael Phnl带领下,专门为自动驾驶开发了一套中文名叫“冰羚”,英文名ICEORYX的中间件。 如上面所说,大量自动驾驶相关的感知数据需要在整个系…

css梯形tab

效果&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Tab 示例</…

LInux 文件系统

目录 认识磁盘 初识inode 磁盘的概念 磁盘分区和格式化介绍 文件系统EXT2的存储方案 Data Blocks : 数据表&#xff0c;存文件内容的区域 inode Table Block bitmap inode bitmap Group Descriptor Table Super Block 如何理解目录 文件的三个时间 认识磁盘 文件…

Linux网络编程

网络&#xff1a;不同主机&#xff0c;进程间通信 目的 1&#xff0c; 解决主机之间的硬件层面的互联互通 2&#xff0c;解决主机间软件层面的互联互通 IP地址&#xff1a;区分不同主机&#xff08;软件地址&#xff09; MAC地址&#xff1a;硬件地址 端口号&#xff1a;区分同…

【JavaScript】07-APIs - DOM + BOM

本文目前介绍JS中的API的知识点&#xff0c;操作案例后续补充。 目录 1. web API基本认知 2. API 作用和分类 2.1 DOM 2.1.1 DOM树 2.1.2 DOM对象 2.1.2.1 操作DOM对象 ① 选中这个标签后才能操作 1. 选择匹配的第一个元素 2. 选择多个元素 3. 获取1个可直接修改 4…

postgresql

作者本人也搭建了一个docker镜像加速器&#xff0c;需要的朋友随时联系作者&#xff0c;镜像加速嘎嘎快&#xff0c;快速解决docker镜像拉不下的问题&#xff0c;文章最后带有作者wx&#xff0c;先好好学习吧。 一&#xff1a;PostgreSQL数据库 1.1&#xff1a;PostgreSQL介绍和…

推荐几款优秀的PDF转电子画册的软件

当然可以&#xff01;以下是几款优秀的PDF转电子画册的软件推荐&#xff0c;内容简洁易懂&#xff0c;这些软件都具有易用性和互动性&#xff0c;适合不同需求的用户使用。​ ❶ FLBOOK&#xff5c;在线创作平台 支持PDF直接导入生成仿真翻页电子书。提供15主题模板与字体库&a…

Spring Boot使用JDBC /JPA访问达梦数据库

Spring Boot 是一个广泛使用的 Java 框架&#xff0c;用于快速构建基于 Spring 的应用程序。对于达梦数据库&#xff08;DMDB&#xff09;的支持&#xff0c;Spring Boot 本身并没有直接内置对达梦数据库的集成&#xff0c;但你可以通过一些配置和依赖来支持达梦数据库。 以下…

2025牛客寒假算法基础集训营6

A.复制鸡 思路&#xff1a;比较简单&#xff0c;略。 void solve() {int n, m, k;cin >> n;int last -1, ans 0;for (int i 0; i<n; i){int x;cin >> x;if (x ! last){ans;}last x;}cout << ans << endl; } B.好伙计猜拳 思路&#xff1a;这…

记录排查服务器CPU负载过高

1.top 命令查看cpu占比过高的进程id 这里是 6 2. 查看进程中占用CPU过高的线程 id 这里是9 top -H -p 6 ps -mp 6 -o THREAD,tid,time 使用jstack 工具 产看进程的日志 需要线程id转换成16进制 jstack 6 | grep “0x9” 4.jstack 6 可以看进程的详细日志 查看日志发现是 垃圾回…

vscode离线配置远程服务器

目录 一、前提 二、方法 2.1 查看vscode的commit_id 2.2 下载linux服务器安装包 2.3 安装包上传到远程服务器&#xff0c;并进行文件解压缩 三、常见错误 Failed to set up socket for dynamic port forward to remote port&#xff08;vscode报错解决方法&#xff09;-C…

Spark(5)host配置

&#xff08;一.)host配置的作用&#xff1a; hosts 文件是一个本地的文本文件&#xff0c;它的作用是将主机名映射到对应的 IP 地址&#xff0c;在 DNS&#xff08;域名系统&#xff09;解析之前&#xff0c;系统会先查询 hosts 文件来确定目标主机的 IP 地址。 &#xff08;二…

CInternetToolbar::_CommonHandleFileSysChange函数分析之CReBar::_IDToIndex函数的作用

第一部分&#xff1a; // IMPORTANT: dont change the value of anything between CBIDX_FIRST and CBIDX_LAST. // CInternetToolbar::_LoadUpgradeSettings assumes these values havent changed from // version to version. #define CBIDX_MENU 1 …

ZYNQ-PL学习实践(五)IP核之FIFO

ZYNQ-PL学习实践&#xff08;四&#xff09;IP核之FIFO&#xff09; 1 概述2 程序2.1 FIFO IP核2.2 写FIFO模块2.3 读FIFO模块2.4 顶层例化模块 3 仿真总结 1 概述 FIFO在fpga应用过程相当于一个先进先出的缓冲器&#xff0c;跨时钟域传输信号传递&#xff0c;采用顺序写入数据…

AI优化SEO关键词精准定位

内容概要 数字营销领域正经历由人工智能驱动的范式革新&#xff0c;尤其在SEO关键词优化层面呈现出颠覆性变革。基于机器学习的语义分析引擎能够对海量搜索数据进行意图解码&#xff0c;通过自然语言处理技术剥离出用户搜索行为背后的真实需求。不同于传统依赖静态词库的优化方…

PGlite:浏览器中运行的PostgreSQL

PGlite 是一款基于 WebAssembly&#xff08;WASM&#xff09;构建的轻量级 PostgreSQL 数据库引擎&#xff0c;旨在简化开发者在浏览器、Node.js、Bun 或 Deno 环境中运行 PostgreSQL。PGlite 无需复杂的安装或配置&#xff0c;特别适合开发测试、本地化应用及快速原型设计。 一…

【Hudi-SQL DDL创建表语法】

CREATE TABLE 命令功能 CREATE TABLE命令通过指定带有表属性的字段列表来创建Hudi Table。 命令格式 CREATE TABLE [ IF NOT EXISTS] [database_name.]table_name[ (columnTypeList)]USING hudi[ COMMENT table_comment ][ LOCATION location_path ][ OPTIONS (options_lis…