【C++】入门C++

1.C++的第一个程序

之前写的C语言文件都是后缀为.c的文件,进入C++后就要把后缀改为.c++了,vs编译器看到是.cpp就会调⽤C++编译器编译。C++兼容C语言的绝大多数语法,所以C语言的 hallo word 依旧可以在C++下使用。

//test.cpp
//c语言的hallo world
#include<stdio.h>
int main() {

	printf("%s", "hallo world\n");

	return 0;
}

当然C++也有自己的输入输出,C++的hallo word长这样:

//test.cpp
//c++的hallo world
#include<iostream>//相当于c语言的.h文件
using namespace std;
int main() {

	cout << "hello world\n";

	return 0;
}

2.命名空间

2.1命名空间的价值

在C/C++ 中,标准库中的函数命名与程序员写的函数命名、程序员和程序员之间的(函数,变量,宏等等)这些可能会存在命名冲突,使用命名空间(namespace)可以有效避免命名冲突,使得代码更加模块化和易于管理。

c语⾔项⽬类似下⾯程序这样的命名冲突是普遍存在的问题,C++引⼊namespace就是为了更好的解决这样的问题
//c语言的命名冲突

#include<stdio.h>
#include<stdlib.h> //rand()函数在这个库中,编译链接后展开

int rand = 10;

int main() {
	//C2365 "rand":重定义,以前的定义是"函数"

	printf("%d", rand);

	return 0;
}

2.2命名空间的定义 

  • 命名空间的定义需要用到namespac关键字,后面接命名空间的名字,然后在加一对{}即可。{}中即为命名空间的成员。命名空间可以定义变量/函数/类型等。
  • 命名空间的本质是定义了一个新的域,这个域跟全局域互相独立,不同的域可以定义同名变量。这样在命名空间中定义一个rand变量就不会和全局域中的rand函数冲突了。
  • C++中有函数局部域,全局域,命名空间域类域,类域。域影响的是编译器在编译时查找一个变量/函数/类型出处(定义或声明)的逻辑,所以有了域的隔离,名字冲突问题自然就解决了。局部域和全局域除了会影响查找逻辑,还会直接影变量的声明周期,而命名空间域和类域不会直接影响变量的生命周期。
  • 命名空间只能定义在全局,它也可以嵌套定义。
  • 项目工程中的多个文件,会将同名的命名空间当成一个,不会有冲突
  • C++的标准库都放在一个std(standard)的命名空间域中

普通的命名空间域定义

#include<iostream>
#include<stdlib.h>

//普通的命名空间定义 jiuwu是这个命名空间的名字

namespace jiuwu
{
	int a = 10;

	int ADD(int a, int b)
	{
		return a + b;
	}

	struct Node
	{
		struct Node* next;
		int val;
	};
}
int main() {
	
	//这的rand是全局域中的rand函数
	printf("%p\n", rand);

	//这是jiuwu命名空间域中的rand变量
	printf("%d\n",jiuwu::a);

	return 0;
}

嵌套定义命名空间域

#include<iostream>
#include<stdlib.h>

//嵌套命名空间定义

namespace XiangMu_1
{
	namespace jiuwu
	{
		int a = 10;

		int ADD(int a, int b)
		{
			return a + b;
		}

		struct Node
		{
			struct Node* next;
			int val;
		};
	}
	namespace sidangkang
	{
		int a = 20;

		int ADD(float a, float b)
		{
			return a + b;
		}

		struct Node
		{
			struct Node* next;
			int val;
		};
	}

}
int main() {
	
	//这的a是命名空间XiangMu_1中的嵌套jiuwu中的a
	printf("%d\n", XiangMu_1::jiuwu::a);

	//这的a是命名空间XiangMu_1中的嵌套sidangkang中的a
	printf("%d\n", XiangMu_1::sidangkang::a);

	return 0;
}

2.3命名空间的使用

编译器在查找一个变量的声明/定义时,默认只会在局部域和全局域中查找,不会到命名空间域中查找,所以以下程序会报错
# include <stdio.h>
namespace jiuwu
{
int a = 0 ;
int b = 1 ;
}
int main ()
{
// 编译报错: error C2065: “a”: 未声明的标识符
printf ( "%d\n" , a);
return 0
}

我们要使用命名空间中定义的变量/函数,有三种方式:  

  • 指定命名空间访问,项目中推荐这种方式。
  • using将命名空间中某个成员展开,项目中经常访问的不存在冲突的成员推荐这种方式。
  • 展开命名空间中全部成员,项目不推荐,冲突风险很大,日常小练习程序为了方便推荐使用。
namespace jiuwu
{
int a = 0;
int b = 1;
}


// 指定命名空间访问
int main()
{
printf("%d\n", jiuwu::a);
printf("%d\n", jiuwu::b);
return 0;
}

// using将命名空间中某个成员展开
using jiuwu::b;
int main()
{
printf("%d\n", N::a);
printf("%d\n", b);
return 0;
}

//将整个命名空间域展开
using namespce jiuwu;
int main()
{
printf("%d\n", a);
printf("%d\n", b);
return 0;
}

3.C++的输入&输出

  • <iostream> 是C++的标准输入/输出库,定于了标准输入输出对象
  • std::cin 是istream的对象,它主要面向窄字符的标准输入流
  • std::cout是ostream的的对象,它主要面向窄字符的标准输出流
  • std::endl是一个函数,流插入输出时,相当于一个换行字符加刷新缓冲区
  • <<是流插入运算符,>>是流提取运算符 (c语言还使用它们做为移位运算符)
  • C++的输入输出非常方便,它不用向printf函数那样指定类型,它可以自己识别类型
  • cout/cin/endl都属于C++的标准库,C++的标准库都放在一个叫std(standard)的命名空间中,所以要同命名空间的使用方法去使用它们
  • <iostream>间接包含了<stdio.h>,使用可以直接使用printf和scanf,vs系列的编译器是这样的,其他编译器可能会报错
#include<iostream>
int main() {
	int a;
	float b;
	char c;

	//cin = scanf 
	//>>从标准输入流中提取数据
	std::cin >> a >> b >> c; //可自动识别数据类型

	//cout = printf
	//<<将数据输入到标准输出流中
	std::cout << a << " "<< b <<" " << c <<std::endl;

	
	return 0;
}

4.缺省参数

  • 缺省参数就是在定义或声明函数时为函数的形参指定一个默认值。在调用参数时,如果没有对应的实参那么就会使用设定好的缺省值,否则使用实参。缺省参数右分为全缺省参数与半缺省参数。
  • 全缺省参数就是将函数所有的新参都设计为缺省参数,半缺省参数就是将函数部分参数设置为缺省参数。C++规定半缺省参数只能从右往左连续缺省
  • 带缺省参数的函数的调用,C++规定只能从左往右连续给实参,不能跳跃给实参。
  • 函数声明定义分离时,规定缺省参数必须在声明中给。
#include<iostream>
using namespace std;
//全缺省
void func(int a = 10, int b = 10, int c = 10)
{
	cout << a << endl << b << endl << c;
}

//半缺省
void func1(int a, int b = 10,int c = 10)
{
	cout << a << endl << b << endl << c;
}

//错误半缺省
void func2(int a = 10, int b, int c)//应从右往左连续设置缺省值
{
	cout << a << endl << b << endl << c;
}



int main() {

	func();//在没有实参时使用设计好的缺省值
	func(1);//传参时,使用指定实参

	func1();//不能再没有设置缺省参数的地方,选着不传实参
	func1(1);//这里至少传一个实参
	func1(1, 2);

	return 0;
}

5.函数重载

C++中规定可以在同一作用域中出现同名函数,但是要求它们的形参不同

//函数重载
// 1、参数类型不同
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(int left, int right)" << endl;
	return double + double;
}

// 2、参数个数不同
void f()
{
cout << "f()" << endl;
}
void f(int a)
{
cout << "f(int a)" << endl;
}

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

//注意!不能仅通过返回值,与返回类型进行函数重载
int Add(int left, int right)
{
	cout << "int Add(int left, int right)" << endl;
	return left + right;
}

double Add(int left, int right)//返回类型不能作为重载的条件
{
	cout << "int Add(int left, int right)" << endl;
	return left + right;
}

6.引用

6.1什么是引用

 引用不是新定义一个变量,而是给现有的变量取一个别名,这个别名并不会新开辟一块内存空间,而是会和被取别名的变量一起使用一块空间。

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

#include<iostream>
using namespace std;
int main() {

	int a = 10;

	//给a这个变量取别名
	int& b = a;
	int& c = a;

	//也可以给别名取别名,但终究还是同一个变量】
	int& d = b;

	//这里我们可以发现它们的内容和地址都是完全一样的
	cout << a << "    " << &a << endl;
	cout << b << "    " << &b << endl;
	cout << c << "    " << &c << endl;
	cout << d << "    " << &d << endl;


	return 0;
}

6.2引用的特性

1.引用在定义时必须初始化

2.同一个变量可以有多个引用

3.引用一旦被初始化,就不能再改变其指向的对象

4.由于:引用一旦被初始化,就不能再改变其指向的对象,所以在使用const修饰引用时只能修饰其“内容”

#include<iostream>
using namespace std;
int main() {

	//引用在定义时必须初始化,否则报错
	//int& a;

	//一个变量可有多个引用
	int b = 10;
	int& c = b;
	int& d = b;

	//这⾥不是让f引⽤b,因为C++引⽤不能改变指向,这里是给f赋值即 f = 10;e = 10
	int e = 20;
	int& f = e;
	cout << f<<endl;
	f = b;
	cout << f<<endl;

    //const修饰引用
    const int& ra = a;//正确

    int& const ra = a;//错误 原因:引用本质上是一个已经绑定了某个对象的别名,其“指向”在初始化后是不可变的。因此,为引用添加 const 修饰其“指向”是没有意义的,也是不被编译器允许的。


	return 0;
}

6.3const引用

当引用一个const对象,必须使用const引用const引用也可以引用普通对象,因为对象的访问权限可以在引用时缩小,但是不能在引用时放大。

当我们引用编译器创建的临时对象时,也需要用const引用。因为临时对象体通常是只读的,对它进行引用而不使用const引用会造成权限的放大

临时对象的产生

1.表达式的结果

某个表达式的结果会被编译器会创建一个临时对象来保存这个结果

//10 + 20 的结果会被存储到临时对象中,然后在赋值给a
int a = 10 + 20;

2.类型转换

当执行显式的类型转换或隐式的类型转换,且转换结果需要被存储时,也可能产生临时对象

//10.2类型转换的结果会被存储在临时对象中,然后在被赋值被a
int b = 10.2;

3.常量引用的绑定

// 编译器会创建一个值为10的临时int对象
const int& a = 10; 

临时对象的生命周期:临时对象的生命周期是自动管理的,并且通常与引用它的作用域相同。一旦引用超出了它的作用域,临时对象就会被销毁。

6.4.指针和引用的区别

  • 在语法层面,引用的创建不需要开空间属于引用对象的别名,而指针的创建需要空间
  • 引用在定义时必须初始化,而指针不用(指针不初始化容易造成野指针问题)
  • 引用在指向一个对象后不能在更改,而指针可以随时更换指向对象
  • 引用可直接访问指向对象,而指针需要解引用
  • sizeof中的含义不同,引用结果为引用对象类型大小,但指针永远是固定的字节(在32位系统上,指针的大小通常是4字节,在64位系统上,指针的大小通常是8字节)

7.内联函数        

内联函数只需要在函数前面加上inline关键字,编译器会在有内联函数的地方选择性的展开,这样就不用新开栈帧了,对效率提升有所帮助

内联函数的展开对于编译器来说只是一个建议,对于程序员不合理的展开,编译器会选择视而不见

内联函数的声明和定义不建议分离在不同的源文件中,这样会导致链接错误。因为inline展开就没有地址,编译器就找不到定义的内联函数

在vs编译器debug状态进行反汇编码的观察,我们发现内联函数并未展开,这是为了方便程序员调试,debug状态下展开内联函数需要设置这两个地方

 

#include<iostream>
using namespace std;

// 正确的宏实现
#define ADD(a, b) ((a) + (b))
// 为什么不能加分号?
// 为什么要加外⾯的括号?
// 为什么要加⾥⾯的括号?

int main() {

	cout << ADD(2, 3) << endl;//如果加了分号就会出现语法错误

	cout << ADD(2, 3) * 4 << endl;//如果不加外面括号->(a)+ (b) * 4,b会先与4乘法运算,跟我们实际需求不符

	int a = 1, b = 2;
	cout << ADD(a | b, b & a) << endl;//如果不加里面的括号->(a | b + b  &a)b 会与 b先进行加法运算

	return 0;
}

8.nullptr

在C++和C中,NULL实际上是一个宏,C++中NULL被替换成 0,C中NULL被替换成(void*)0。但是无论这两种定义,在C++中使用它们的时候都会出一些问题,例如:

void func(int);  
void func(int*);

假如你想调用 void func(int*);你可能会这样做:

func(NULL);

但是由于NULL被替换成了字面量0,所以你实际上调用的是int版本的func函数

你还可能会这样做:

funk((void*)NULL);

这样写在C++中也是错误的,因为在C++中void*指针不能够隐形的转化为其他类型的指针,在C语言中这样写是可以的,因为C语言中的void*指针可以给给任意类型的指针

所以在C++11中引入了nullptr关键字。nullptr实际上是一种特殊的字面量,它能够隐形的转化成任意类型的指针,而不能过转化成整数类型

#include<iostream>
using namespace std;
void func(int a)
{
	cout << "func(int a)" << endl;
}
void func(int* a)
{
	cout << "func(int* a)" << endl;
}
int main() {

	func(NULL);
	//func((void*)NULL);

	func(nullptr);

	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

紫光同创——盘古 50KN 网口板

本原创文章由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处&#xff08;www.meyesemi.com) 一、开发系统介绍 盘古 50KN 网口板开发板&#xff08;MES50H-Ethernet&#xff09;采用了核心板扩展板的结 构&#…

本篇文章来介绍下dockerfile

我开始玩儿docker的时候&#xff0c;都是通过docker pull命令把基础镜像拉取到本地&#xff0c;然后在跑成容器&#xff0c;在操作容器&#xff0c;做一些自己的事情&#xff0c;比如安装个java环境什么的&#xff0c;直到我接触到了dockerfile&#xff0c;我发现dockerfile真是…

一款基于.NET8开源且免费的中小型酒店管理系统

项目介绍 TopskyHotelManagerSystem是一款基于.NET8开源、免费&#xff08;MIT License&#xff09;的中小型酒店管理系统&#xff0c;为中小型酒店提供全面的酒店管理系统解决方案&#xff0c;帮助酒店提高运营效率&#xff0c;优化客户体验。 开发目的 在现如今发展迅速的酒…

【本科毕业设计】基于单片机的智能家居防火防盗报警系统

基于单片机的智能家居防火防盗报警系统 源码下载摘要Abstract第1章 绪论1.1课题的背景1.2 研究的目的和意义 第2章 系统总体方案设计2.1 设计要求2.2 方案选择和论证2.2.1 单片机的选择2.2.2 显示方案的选择 第3章 系统硬件设计3.1 整体方案设计3.1.1 系统概述3.1.2 系统框图 3…

【测试平台】打包 子节点ios环境配置

主要记录如何配置ios打包机环境&#xff0c;ios环境相对来说比较简单的&#xff0c;研发配置好证书可以本地打包&#xff0c;接入流程比较简单了。 打包机系统升级 1.升级mac OS系统 一般升级好几个小时&#xff0c;可以晚上下载好 2.下载xcode并安装 Appstroe 下载安装xco…

分布式光伏是什么意思?如何高效管理?

分布式光伏系统是指在用户现场或靠近用电现场配置较小的光伏发电供电系统&#xff0c;以满足特定用户的需求。根据通知&#xff0c;分布式光伏系统主要有以下几类定义&#xff1a; 10kV以下电压等级接入&#xff0c;且单个并网点总装机容量不超过6MW的分布式电源&#xff1a;这…

初识WebGL

思路&#xff1a; 构建<canvas>画布节点&#xff0c;获取其的实例。使用getWebGLContext() 拿到画布上下文。拿到上下文用clearColor() 设置背景颜色。最后清空canvas画布,是为了清除颜色缓冲区。 html结构&#xff1a; <!DOCTYPE html> <html lang"en&…

微信小程序时间弹窗——年月日时分

需求 1、默认当前时间2、选择时间弹窗限制最大值、最小值3、每次弹起更新最大值为当前时间&#xff0c;默认值为上次选中时间4、 minDate: new Date(2023, 10, 1).getTime(),也可以传入时间字符串new Date(2023-10-1 12:22).getTime() html <view class"flex bb ptb…

redis部署手册

文章目录 一、 环境配置资源配置操作系统资源配置服务器1服务器2服务器3 目录规划 二、Redis软件部署2.1 上传相关软件包2.2 安装软件2.3 修改配置文件2.3.1 修改redis.conf2.3.2 修改sentinel.conf2.3.3 启动2.3.4 安装完成 三、Redis的哨兵恢复3.1 现象3.2 解决方法 一、 环境…

SD-WAN分布式组网:构建高效、灵活的企业网络架构

随着企业数字化转型的深入&#xff0c;分布式组网逐渐成为企业网络架构中的核心需求。无论是跨区域的分支机构互联&#xff0c;还是企业与云服务的连接&#xff0c;如何在不同区域实现高效、低延迟的网络传输&#xff0c;已成为业务成功的关键。SD-WAN&#xff08;软件定义广域…

#PCIE#基础知识分解之 CC/SRNS/SRIS 时钟架构

参考资料为PCIe Base Spec和CEM Spec。 1.1 时钟架构分类 PCIe参考时钟的三种架构&#xff1a; Common Refclk (Shared Refclk) ArchitectureData Clocked Rx ArchitectureSeparate Refclk Architecture 下面&#xff0c;我们来简单地聊一聊前面说到的三种参考时钟架构&…

开源一款前后端分离的企业级网站内容管理系统,支持站群管理、多平台静态化,多语言、全文检索的源码

大家好&#xff0c;我是一颗甜苞谷&#xff0c;今天分享一款前后端分离的企业级网站内容管理系统&#xff0c;支持站群管理、多平台静态化&#xff0c;多语言、全文检索的源码。 前言 在当今的数字化时代&#xff0c;企业网站和个人博客已成为信息传播和品牌建设的重要渠道。…

Linux系统基础-多线程超详细讲解(2)_线程控制

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 Linux系统基础-多线程超详细讲解(2)_线程控制 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f4…

「C/C++」C/C++ 之 判断语句

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

2024年10月HarmonyOS应用开发者基础认证全新题库

注意事项&#xff1a;切记在考试之外的设备上打开题库进行搜索&#xff0c;防止切屏三次考试自动结束&#xff0c;题目是乱序&#xff0c;每次考试&#xff0c;选项的顺序都不同 这是基础认证题库&#xff0c;不是高级认证题库注意看清楚标题 高级认证题库地址&#xff1a;20…

go语言进阶之并发基础

并发 什么是并发&#xff0c;也就是我们常说的多线程&#xff0c;多个程序同时执行。 并发的基础 线程和进程 进程 进程是操作系统中一个重要的概念&#xff0c;指的是一个正在运行的程序的实例。它包含程序代码、当前活动的状态、变量、程序计数器和内存等资源。进程是系…

迷你航拍高清智能无人机技术详解

迷你航拍高清智能无人机技术是一种结合了高清影像拍摄、智能控制、稳定悬停以及便携性等特点的无人机技术。以下是对该技术的详细解析&#xff1a; 一、技术特点 1. 高清影像拍摄&#xff1a; 高分辨率传感器&#xff1a;迷你航拍无人机通常搭载高分辨率的相机传感器&#xf…

macOS Sonoma 14.7.1 (23H222) Boot ISO 原版可引导镜像下载

macOS Sonoma 14.7.1 (23H222) Boot ISO 原版可引导镜像下载 2024 年 10 月 28 日&#xff0c;Apple 智能今日登陆 iPhone、iPad 和 Mac。用户现可借助 Apple 智能优化写作&#xff0c;为通知、邮件和消息生成摘要&#xff0c;体验交互更自然、功能更丰富的 Siri&#xff0c;使…

QT交互界面:实现按钮运行脚本程序

一.所需运行的脚本 本篇采用上一篇文章的脚本为运行对象&#xff0c;实现按钮运行脚本 上一篇文章&#xff1a;从0到1&#xff1a;QT项目在Linux下生成可以双击运用的程序&#xff08;采用脚本&#xff09;-CSDN博客 二.调用脚本的代码 widget.cpp中添加以下代码 #include &…

玄机-流量特征分析-常见攻击事件 tomcat

简介 在web服务器上发现的可疑活动,流量分析会显示很多请求,这表明存在恶意的扫描行为,通过分析扫描的行为后提交攻击者IP flag格式&#xff1a;flag{ip}&#xff0c;如&#xff1a;flag{127.0.0.1} 找到攻击者IP后请通过技术手段确定其所在地址 flag格式: flag{城市英文小写…