【C++】入门C++

news2024/11/29 10:31:51

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;
}

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

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

相关文章

快速上手机器学习-朴素贝叶斯

朴素贝叶斯 引言&#xff1a;本文通过介绍先验概率&#xff0c;后验概率&#xff0c;条件概率计算和贝叶斯定理等概率论内容引入朴素贝叶斯分类算法的基本思路&#xff0c;朴素贝叶斯的最终分类思想是将输入分类给概率最大的类&#xff0c;这也是概率模型算法的共有思想。本文专…

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

背景 本文记录不是安卓Gradle打包&#xff0c;因为我们google play提审&#xff0c;为了规避跟下架包的相似度避免马甲包封号&#xff0c;使用混淆逻辑。 打包环境部署 申请对应虚拟机会有两个账号root和admin&#xff0c;主要避免root账号权限过高造成脚本误操作。这里面问题…

模型融合新趋势!Transformer领域专家纷纷布局,高分成果轻松达成!

今天给大家分享一个能发A会且不卷的方向&#xff1a;模型融合&#xff01; 光是ICLR2025的投稿&#xff0c;其增长就跃升至前30&#xff0c;可见热度很高&#xff01;但相比其他领域&#xff0c;总量还不大&#xff0c;相对蓝海&#xff0c;创新空间很大。 其所以这么热门&am…

1.机器人抓取与操作介绍-深蓝学院

介绍 操作任务 操作 • Insertion • Pushing and sliding • 其它操作任务 抓取 • 两指&#xff08;平行夹爪&#xff09;抓取 • 灵巧手抓取 7轴 Franka 对应人的手臂 6轴 UR构型去掉一个自由度 课程大纲 Robotic Manipulation 操作 • Robotic manipulation refers…

spark豆瓣书籍推荐系统-计算机毕业设计源码53447

摘要 本论文主要论述了如何基于Spark开发一个豆瓣书籍推荐系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述豆瓣书籍推荐系统的当前背景以及系统开发的目的&#xff0c;后续章节将严…

macOS开发环境配置与应用开发教程

macOS开发环境配置与应用开发教程 引言 macOS是一个强大的操作系统&#xff0c;广泛应用于软件开发&#xff0c;尤其是iOS和macOS应用开发。本文将详细介绍如何配置macOS开发环境&#xff0c;并通过实例演示如何进行应用开发。希望通过这篇文章&#xff0c;帮助读者快速上手m…

Unity吃鸡背包系统笔记

功能需求 查看玩家拥有的所有物品&#xff0c;可以放下其中的任意物品&#xff1b;查看已死的他人背包的物品&#xff0c;可以拿起其中的任意物品&#xff1b;查看附近的物品&#xff0c;可以拿起其中的任意物品&#xff08;暂时不考虑背包容量&#xff09;&#xff1b; 难点 …

《Linux系统编程篇》fork函数——基础篇

文章目录 引言fork() 函数概述父子进程 fork函数fork() 的常见问题fork() 的优势与限制 结论 命为志存。 —— 朱熹 引言 《Linux系统编程篇》——基础篇首页传送门 本节我们正式进入Linux的进程代码编写。 fork() 是 Unix 系统中一个重要的系统调用&#xff0c;用于创建一个…

MySQL 8 下载与安装攻略

MySQL是一个流行的关系型数据库管理系统&#xff0c;目前MySQL属于Oracle公司的&#xff0c;关于MySQL的详细介绍可以参考&#xff1a; MySQL 的完整介绍 本篇主要关注MySQL 的下载和安装。 MySQL 下载 官方下载 进入MySQL 的下载页面 &#xff1a;https://dev.mysql.com/do…

HarmonyOS 鸿蒙开发 路由跳转报错this uri is empty, not support in route push.

检查方案1&#xff1a; 工程目录下 entry > src > main > resources > base > profile > main_pages.json中检查是否配置了NextPage 检查方案2&#xff1a; 在路由跳转的代码中检查是否路径配置错误 这里要注意&#xff0c;url的路径一定要和main_pages.json…

芯片上音频相关的验证

通常芯片设计公司&#xff08;比如QUALCOMM&#xff09;把芯片设计好后交由芯片制造商&#xff08;比如台积电&#xff09;去生产&#xff0c;俗称流片。芯片设计公司由ASIC部门负责设计芯片。ASIC设计的芯片只有经过充分的验证&#xff08;这里说的验证是FPGA&#xff08;现场…

【VSCode】配置

安装插件 C vscode-icons gdb调试 https://www.bilibili.com/video/BV15U4y1x7b2/?spm_id_from333.999.0.0&vd_sourcedf0ce73d9b9b61e6d4771898f1441f7f https://www.bilibili.com/video/BV1pU4y1W74Z?spm_id_from333.788.recommend_more_video.-1&vd_sourcedf0…

springboot使用枚举作为接口的参数

1.定义枚举类 2.定义接口 3.具体实现方法 4.apifox传入参数 枚举的具体’名称’就可以了 5.调试 6.进入断点&#xff0c;这样我们发现在接口的参数就映射到应的枚举类上了

数据结构(8.4_3)——堆的插入删除

在堆中插入新元素 在堆中删除元素 总结&#xff1a;

《计算机网络网络层:连接虚拟世界的关键桥梁》

一、网络层概述 网络层在计算机网络中占据着至关重要的地位&#xff0c;它作为连接不同网络的关键层次&#xff0c;起着承上启下的作用。网络层的主要任务是实现网络互连&#xff0c;将数据设法从源端经过若干个中间节点传送到目的端&#xff0c;为分组交换网上的不同主机提供通…

【linux】fdisk磁盘分区管理

介绍 fdisk是一个磁盘分区管理工具&#xff0c;可以用来创建、删除、修改和查看磁盘分区。 fdisk一般都是交互式使用&#xff0c;基础语法: fdisk /dev/sdd。进入交互窗口后&#xff0c;有一些选项&#xff0c;需要了解下&#xff1a; 选项含义n创建新分区p查看磁盘的分区情…

项目成本管理系统有哪些功能?9款工具详解

本文推荐的9大主流项目成本管理工具有: 1. PingCode&#xff1b;2. Worktile&#xff1b;3. 用友U8项目管理&#xff1b;4. 金蝶K3 Cloud&#xff1b;5. 泛微e-Project&#xff1b;6. 亿方云项目管理&#xff1b; 7. SAP Project System&#xff1b; 8. Trello&#xff1b; 9. …

基于opencv的眼镜试戴系统

对于正在准备毕业设计或者想在技术项目上加点“创新”的同学们&#xff0c;推荐一款基于OpenCV的眼镜试戴系统&#xff01;这不仅是一个实现个人创意的项目&#xff0c;更是一个结合AI技术和实用应用的完美范例。 &#x1f31f; 系统核心功能&#xff1a; 图片试戴&#xff1a…

解决cuda环境使用dgl

Dgl 是实现图结构数据构造的工具包&#xff0c;想在gpu环境下使用它&#xff0c;如果安装的是pip install dgl 会有下面错误 dgl._ffi.base.DGLError: [09:10:13] /opt/dgl/src/runtime/c_runtime_api.cc:82: Check failed: allow_missing: Device API cuda is not enabled. P…

软考高级备考记录

一 报考条件和报名流程 报考条件 该考试具有水平考试性质&#xff0c;报考任何级别不需要学历、资历条件&#xff0c;只要达到相应的专业技术水平就可以报考相应的级别 报名流程 软考报名官网&#xff1a;中国计算机技术职业资格网 官网上有 报名时间&#xff0c;考试…