c++领域展开第一幕——入门基础(命名空间、iostream、缺省参数、函数重载、nullptr、inline(内联函数))超详细!!!!

news2024/12/27 2:15:28

在这里插入图片描述

文章目录

  • 前言
  • 一、c++的第一个程序
  • 二、命名空间
    • 2.1 namespace 的价值
    • 2.2 namespace 的定义
    • 2.3 命名空间的使用
  • 三、c++的输入和输出
  • 四、缺省参数
  • 五、函数重载
  • 六、nullptr
  • 七、inline
  • 总结

前言

今天小编带着大家进入c++的大门,虽然c++难,但好事多磨,一起来慢慢啃下这个硬骨头吧
今天大致会了解c++的入门基础部分,fellow me

一、c++的第一个程序

C++兼容C语言绝大多数的语法,所以C语言实现的hello world依旧可以运行,C++中需要把定义文件代码后缀改为.cpp,vs编译器看到是.cpp就会调用C++编译器编译,linux下要用g++编译,不再是gcc

// test.cpp
#include<stdio.h>
int main()
{
	printf("hello world\n");
	return 0;
}

当然C++有一套自己的输入输出,严格说C++版本的hello world应该是这样写的。

#include<iostream>
using namespace std;
int main()
{
	cout << "hello world\n" << endl;
	return 0;
}

二、命名空间

2.1 namespace 的价值

在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。\

c语言项目类似下面程序这样的命名冲突是普遍存在的问题C++引入namespace就是为了更好的解决这样的问题

#include <stdlib.h>
int rand = 10;
int main()
{
	// 编译报错: “rand”: 重定义;以前的定义是“函数”
	printf("%d\n", rand);
return 0;
}

2.2 namespace 的定义

定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量/函数/类型等。
namespace本质是定义出一个域这个域跟全局域各自独立,不同的域可以定义同名变量,所以下面的rand不在冲突了。

namespace xxx
{
	namespace yyy   //   嵌套定义  
	{
		int rand = 1;
		int Add(int left, int right)
		{
			return left + right;
		}
	}
	namespace zzz
	{
		int rand = 2;
		int Add(int left, int right)
		{
			return (left + right) * 10;
		}
	}
}
int main()
{
	printf("%d\n", xxx::yyy::rand);
	printf("%d\n", xxx::zzz::rand);
	printf("%d\n", xxx::yyy::Add(1, 2));
	printf("%d\n", xxx::zzz::Add(1, 2));
	return 0;
}

在这里插入图片描述
有代码和运行截图,才能更好的理解

C++中域有函数局部域,全局域,命名空间域,类域;域影响的是编译时语法查找一个变量/函数/类型出处(声明或定义)的逻辑,所以有了域隔离,名字冲突就解决了。局部域和全局域除了会影响编译查找逻辑,还会影响变量的生命周期,命名空间域和类域不影响变量生命周期。

namespace只能定义在全局,当然他还可以嵌套定义
项目工程中多文件中定义的同名namespace会认为是一个namespace,不会冲突。
C++标准库都放在一个叫std(standard)的命名空间中。

2.3 命名空间的使用

编译查找一个变量的声明/定义时,默认只会在局部或者全局查找,不会到命名空间里面去查找。所以下面程序会编译报错。所以我们要使用命名空间中定义的变量/函数,有三种方式:
指定命名空间访问,项目中推荐这种方式。
using将命名空间中某个成员展开,项目中经常访问的不存在冲突的成员推荐这种方式
展开命名空间中全部成员,项目不推荐,冲突风险很大,日常小练习程序为了方便推荐使用。

#include<stdio.h>
namespace N
{
	int a = 0;
	int b = 1;
}
int main()
{
	// 编译报错: “a”: 未声明的标识符
	printf("%d\n", a);
	return 0;
}
	// 指定命名空间访问
int main()
{
	printf("%d\n", N::a);
	return 0;
}
// using将命名空间中某个成员展开
using N::b;
int main()
{
	printf("%d\n", N::a);
	printf("%d\n", b);
	return 0;
}
// 展开命名空间中全部成员
using namespace N;
int main()
{
	printf("%d\n", a);
	printf("%d\n", b);
	return 0;
}

三、c++的输入和输出

• 是 Input Output Stream 的缩写,是标准的输入、输出流库,定义了标准的输入、输出对象。
std::cin 是 istream 类的对象,它主要面向窄字符的标准输入流。
• std::cout 是 ostream 类的对象,它主要面向窄字符的标准输出流。

• std::endl 是一个函数,流插入输出时,相当于插入一个换行字符加刷新缓冲区。
• <<是流插入运算符,>>是流提取运算符。(C语言还用这两个运算符做位运算左移/右移
• 使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动指定格式,C++的输入输出可以自动识别变量类型,其实最重要的是
C++的流能更好的支持自定义类型对象的输入输出
• IO流涉及类和对象,运算符重载、继承等很多面向对象的知识,我们后续会慢慢学习的,所以这里我们只能简单认识一下C++ IO流的用法。
• cout/cin/endl等都属于C++标准库,C++标准库都放在一个叫std(standard)的命名空间中,所以要通过命名空间的使用方式去用他们
一般日常练习中我们可以using namespace std,实际项目开发中不建议using namespace std。
• 这里我们没有包含<stdio.h>,也可以使用printf和scanf,在包含间接包含了。vs系列编译器是这样的,其他编译器可能会报错。

#include <iostream>
using namespace std;
int main()
{
	int a = 0;
	double b = 0.1;
	char c = 'x';
	cout << a << " " << b << " " << c << endl;
	std::cout << a << " " << b << " " << c << std::endl;
	scanf("%d%lf", &a, &b);
	printf("%d %lf\n", a, b);
	// 可以自动识别变量的类型
	cin >> a;
	cin >> b >> c;
	cout << a << endl;
	cout << b << " " << c << endl;
	return 0;
}

cin和cout用起来还是很爽的

四、缺省参数

缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参,缺省参数分为全缺省和半缺省参数。(有些地方把缺省参数也叫默认参数)
全缺省就是全部形参给缺省值半缺省就是部分形参给缺省值半缺省参数必须从右往左依次连续缺省,不能间隔跳跃给缺省值。
带缺省参数的函数调用,C++规定必须从左到右依次给实参,不能跳跃给实参
函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省值。

#include <iostream>
using namespace std;
void Func(int a = 0)
{
	cout << a << endl;
}
int main()
{
	Func(); // 没有传参时,使用参数的默认值
	Func(10); // 传参时,使用指定的实参
	return 0;
}
#include <iostream>
using namespace std;
// 全缺省
void Func1(int a = 10, int b = 20, int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}
// 半缺省
void Func2(int a, int b = 10, int c = 20)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}
int main()
{
	Func1();
	Func1(1);
	Func1(1,2);
	Func1(1,2,3);
	Func2(100);
	Func2(100, 200);
	Func2(100, 200, 300);
	return 0;
}

在这里插入图片描述
可以仔细看看代码体会一下

还有一点要注意的是,缺省参数只能在函数的声明部分给,不能在定义部分给

// Stack.h   .h文件  函数的声明  这里用以前实现过的栈举例子
#include <iostream>
#include <assert.h>
using namespace std;
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;
	void STInit(ST* ps, int n = 4);   //  这里的n = 4  就是缺省参数 
// Stack.cpp   函数的定义文件  
#include"Stack.h"
// 缺省参数不能声明和定义同时给
void STInit(ST* ps, int n)  //  函数的定义  这部分不能给缺省值 
{
	assert(ps && n > 0);
	ps->a = (STDataType*)malloc(n * sizeof(STDataType));
	ps->top = 0;
	ps->capacity = n;
}
// test.cpp   测试文件 
#include"Stack.h"
int main()
{
	ST s1;
	//  不确定数据的多少,这里不传参数,函数会用默认参数  
	STInit(&s1);
	ST s2;
	// 确定知道要插入1000个数据,初始化时一把开好,避免扩容
	STInit(&s2, 1000);
	return 0;
}

五、函数重载

C++支持在同一作用域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者类型不同。这样C++函数调用就表现出了多态行为,使用更灵活。C语言是不支持同一作用域中出现同名函数的。

参数类型不同

#include<iostream>
using namespace std;
int Add(int left, int right)
{
	cout << "int Add(int left, int right)" << endl;
	return left + right;
}
double Add(double left, double right)
{
	cout << "double Add(double left, double right)" << endl;
	return left + right;
}

参数个数不同

void f()
{
	cout << "f()" << endl;
}
void f(int a)
{
	cout << "f(int a)" << endl;
}

参数顺序类型不同

// 3、参数类型顺序不同
void f(int a, char b)
{
	cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
	cout << "f(char b, int a)" << endl;
}

需要注意一些情况

// 返回值不同不能作为重载条件,因为调用时也无法区分
void fxx()
{}
int fxx()
{
	return 0;
}
// 下面两个函数构成重载
// f()但是调用时,会报错,存在歧义,编译器不知道调用谁  这里就是参数缺省背锅了
void f1()
{
	cout << "f()" << endl;
}
void f1(int a = 10)
{
	cout << "f(int a)" << endl;
}

六、nullptr

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

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

C++中NULL可能被定义为字面常量0,或者C中被定义为无类型指针(void)的常量*。不论采取何种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦,本想通过f(NULL)调用指针版本的f(int)函数,但是由于NULL被定义成0,调用了f(int x),因此与程序的初衷相悖。f((void)NULL);调用会报错。**
• C++11中引入nullptr,nullptr是一个特殊的关键字nullptr是一种特殊类型的字面量,它可以转换成任意其他类型的指针类型。使用nullptr定义空指针可以避免类型转换的问题,因为nullptr只能被隐式地转换为指针类型,而不能被转换为整数类型。

#include<iostream>
using namespace std;
void f(int x)
{
	cout << "f(int x)" << endl;
}
void f(int* ptr)
{
	cout << "f(int* ptr)" << endl;
}
int main()
{
	f(0);
	// 本想通过f(NULL)调用指针版本的f(int*)函数,但是由于NULL被定义成0,调用了f(intx),因此与程序的初衷相悖。
	f(NULL);
	f((int*)NULL);
	// 编译报错: “f”: 2 个重载中没有一个可以转换所有参数类型
	// f((void*)NULL);
	f(nullptr);
	return 0;
}

所以c++部分尽量就用nullptr就好啦

七、inline

• 用inline修饰的函数叫做内联函数,编译时C++编译器会在调用的地方展开内联函数这样调用内联函数就不需要建立栈帧了,就可以提高效率。
• inline对于编译器而言只是一个建议,也就是说,你加了inline编译器也可以选择在调用的地方不展开,不同编译器关于inline什么情况展开各不相同,因为C++标准没有规定这个inline适用于频繁调用的短小函数,对于递归函数,代码相对多一些的函数,加上inline也会被编译器忽略
也就是说,在inline这个方面,编译器占主导地位

• C语言实现宏函数也会在预处理时替换展开,但是宏函数实现很复杂很容易出错的,且不方便调试,C++设计了inline目的就是替代C的宏函数。
• vs编译器 debug版本下面默认是不展开inline的,这样方便调试
inline不建议声明和定义分离到两个文件,分离会导致链接错误。因为inline被展开,就没有函数地址,链接时会出现报错。

这里内联函数就是展开的,没有特别多的消耗,如果一个简短的函数调用次数很多很多,这个时候就可以用内联展开,减少函数栈帧的创建,提高效率

#include<iostream>
using namespace std;
inline int Add(int x, int y)
{
	int ret = x + y;
	ret += 1;
	ret += 1;
	ret += 1;
	return ret;
}
int main()
{
	int ret = Add(1, 2);
	cout << Add(1, 2) * 5 << endl;
	return 0;
}
#include<iostream>
using namespace std;
// 实现一个ADD宏函数的常见问题
//#define ADD(int a, int b) return a + b;  这三个是一些错误的宏的实现 
//#define ADD(a, b) a + b;
//#define ADD(a, b) (a + b)
// 正确的宏实现
#define ADD(a, b) ((a) + (b))   //  每个参数都加括号是  因为 a 也可能是一个表达式或者是其他的情况
int main()
{
	int ret = ADD(1, 2);
	cout << ADD(1, 2) << endl;
	cout << ADD(1, 2)*5 << endl;
	int x = 1, y = 2;
	ADD(x & y, x | y); // -> (x&y+x|y)
	return 0;
}

总结

今天入门了c++的基本语法,从第一个c++程序到命名空间对c语言命名冲突的优化,再来到缺省参数的魅力,然后是函数重载,接着是nullptr和NULL的区别以及优点,最后是类似于宏函数但优于宏函数的内联函数
c++在各个方面都在优化c语言,把以前不能实现或者有缺点的都进行了优化,不愧是c puls puls
今天的学习就到这里啦,下一篇博客小编将带着大家学习一个比指针好用的东西,不要走开,小编持续更新中~~~

在这里插入图片描述

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

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

相关文章

Java Web 1HTML快速入门

目录 一、Web开发介绍 1.什么是Web&#xff1f; 2.初识Web前端 二、HTML快速入门 1.什么是HTML、CSS&#xff1f; 2、案例练习 3.小结 三、VS Code开发工具 四、基础标签&样式&#xff08;HTML&#xff09; 2、实现标题--样式1&#xff08;新闻标题的颜色&#xff0…

【Python网络爬虫笔记】7-网络爬虫的搜索工具re模块

目录 一、网络爬虫中的正则表达式和re模块&#xff08;一&#xff09;数据提取的精确性&#xff08;二&#xff09;处理复杂的文本结构&#xff08;三&#xff09;提高数据处理效率 二、正则表达式的内涵&#xff08;一&#xff09;、常用元字符&#xff08;二&#xff09;、量…

42_GAN网络详解(2)---常见的GAN

DCGAN CGAN 条件生成对抗网络&#xff08;Conditional Generative Adversarial Networks, CGAN&#xff09;是生成对抗网络&#xff08;Generative Adversarial Networks, GAN&#xff09;的一种变体&#xff0c;由Mehdi Mirza和Simon Osindero在2014年提出。CGAN的主要改进在…

PC端阅读器--koodo reader

官网&#xff1a;请在必应搜索引擎上输入 koodo reader GitHub&#xff1a;GitHub - koodo-reader/koodo-reader: Windows, macOS, Linux and Web 123云windows版&#xff1a;Koodo-Reader-1.5.1.exe下载 提取码&#xff1a;4455 优&#xff1a; 1.开源&#xff0c;懂&#x…

PyQt设计界面优化 #qss #ui设计 #QMainWindow

思维导图 通过qss实现ui界面设计优化 Qss是Qt程序界面中用来设置控件的背景图片、大小、字体颜色、字体类型、按钮状态变化等属性&#xff0c;它是用来美化UI界面。实现界面和程序的分离&#xff0c;快速切换界面。 首先我们在Pytchram创建一个新目录 然后将我们所需要的图片打…

多维数组及其应用————13

1. 二维数组 如果我们把 ⼀维数组做为数组的元 素&#xff0c;这时候就是⼆维数组&#xff0c; ⼆维数组作为数组元素的数组被为三维数组&#xff0c;⼆维数组以上的数组统称 为多维数组。 1.1 二维数组的创建 先行后列 其实也可以这样理解&#xff1a;把二维数组当成特殊的一维…

基于Java Springboot校园导航微信小程序

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse微信开发…

k8s,声明式API对象理解

命令式API 比如&#xff1a; 先kubectl create&#xff0c;再replace的操作&#xff0c;我们称为命令式配置文件操作 kubectl replace的执行过程&#xff0c;是使用新的YAML文件中的API对象&#xff0c;替换原有的API对象&#xff1b;而kubectl apply&#xff0c;则是执行了一…

【北京迅为】iTOP-4412全能版使用手册-第三十五章 WEB控制LED

iTOP-4412全能版采用四核Cortex-A9&#xff0c;主频为1.4GHz-1.6GHz&#xff0c;配备S5M8767 电源管理&#xff0c;集成USB HUB,选用高品质板对板连接器稳定可靠&#xff0c;大厂生产&#xff0c;做工精良。接口一应俱全&#xff0c;开发更简单,搭载全网通4G、支持WIFI、蓝牙、…

轻量的基于图结构的RAG方案LightRAG

LightRAG出自2024年10月的论文《LIGHTRAG: SIMPLE AND FASTRETRIEVAL-AUGMENTED GENERATION》(github)&#xff0c;也是使用图结构来索引和搜索相关文本。 LightRAG作者认为已有的RAG系统有如下两个限制&#xff0c;导致难以回答类似"How does the rise of electric vehi…

分布式cap

P&#xff08;分区安全&#xff09;都能保证&#xff0c;就是在C&#xff08;强一致&#xff09;和A&#xff08;性能&#xff09;之间做取舍。 &#xff08;即立马做主从同步&#xff0c;还是先返回写入结果等会再做主从同步。类似的还有&#xff0c;缓存和db之间的同步。&am…

AD7606使用方法

AD7606是一款8通道最高16位200ksps的AD采样芯片。5V单模拟电源供电&#xff0c;真双极性模拟输入可以选择10 V&#xff0c;5 V两种量程。支持串口与并口两种读取方式。 硬件连接方式&#xff1a; 配置引脚 引脚功能 详细说明 OS2 OS1 OS2 过采样率配置 000 1倍过采样率 …

[VUE]框架网页开发02-如何打包Vue.js框架网页并在服务器中通过Tomcat启动

在现代Web开发中&#xff0c;Vue.js已经成为前端开发的热门选择之一。然而&#xff0c;将Vue.js项目打包并部署到生产环境可能会让一些开发者感到困惑。本文将详细介绍如何将Vue.js项目打包&#xff0c;并通过Tomcat服务器启动运行。 1. 准备工作 确保你的项目能够正常运行,项…

服务器与普通电脑有什么区别?

服务器和普通电脑&#xff08;通常指的是个人计算机&#xff0c;即PC&#xff09;有众多相似之处&#xff0c;主要构成包含&#xff1a;CPU&#xff0c;内存&#xff0c;芯片&#xff0c;I/O总线设备&#xff0c;电源&#xff0c;机箱及操作系统软件等&#xff0c;鉴于使用要求…

2.2 线性表的顺序表示

2.2.1 顺序表的定义 一、顺序表的基本概念 线性表的顺序存储又称顺序表。 它是用一组地址连续的存储单元依次存储线性表中的数据元素&#xff0c;从而使得逻辑上相邻的连个元素在物理上也相邻。 第1个元素存储在顺序表的起始位置&#xff0c;第i个元素存储位置后面紧接着存…

游戏引擎学习第30天

仓库: https://gitee.com/mrxiao_com/2d_game 回顾 在这段讨论中&#xff0c;重点是对开发过程中出现的游戏代码进行梳理和进一步优化的过程。 工作回顾&#xff1a;在第30天&#xff0c;回顾了前一天的工作&#xff0c;并提到今天的任务是继续从第29天的代码开始&#xff0c…

探索HarmonyOS:一键掌握Router与NavPathStatck的传参和页面回调技巧

路由的选择 HarmonyOS提供两种路由实现的方式&#xff0c;分别是 Router 和 NavPatchStack。两者使用场景和特效各有优劣。 组件适用场景特点备注Router模块间与模块内页面切换通过每个页面的url实现模块间解耦NavPathStack模块内页面切换通过组件级路由统一路由管理 什么时候使…

每日计划-1203

1. 完成 236. 二叉树的最近公共祖先 ​ /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/ class Solution {public:TreeNode* lowe…

【AI系统】Auto-Tuning 原理

Auto-Tuning 原理 在硬件平台驱动算子运行需要使用各种优化方式来提高性能&#xff0c;然而传统的手工编写算子库面临各种窘境&#xff0c;衍生出了自动生成高性能算子的的方式&#xff0c;称为自动调优。在本文我们首先分析传统算子库面临的挑战&#xff0c;之后介绍基于 TVM…

多组学数据如何发表高分SCI论文,以RNA-Seq数据为例

随着高通量测序以及生物信息学的发展&#xff0c;R语言在生物大数据分析以及数据挖掘中发挥着越来越重要的作用。想要成为一名优秀的生物数据分析者与科研团队不可或缺的人才&#xff0c;除了掌握对生物大数据挖掘与分析技能之外&#xff0c;还要具备一定的统计分析能力与SCI论…