C++之一:基础

news/2024/12/18 1:40:21/

相关代码:cpp/month12/test_12/main.cpp · Hera_Yc/bit_C_学习 - 码云 - 开源中国

C++面向对象的语言

C++兼容C:因此,C++亦可以是面向过程的语言。

         C++的基础知识是特别碎的,但这并不意味着这些知识并不重要,这些碎片化的内容是类和对象的基础,每一个知识后面都有很多的扩展,本文并不会讲解扩展内容,仅仅只是作为C++的基础来学习。不需要读者去深挖其中的含义。

一、命名空间

1、定义

 定义命名空间,需要使用到namespace关键字。

namespace N1
{int a = 10;int b = 20;int func(int a, int b){return a + b;}
}
  1. 命名空间可以嵌套定义。
  2. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
  3. 一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中 
2、使用

命名空间的使用有三种方式:

  • 在变量前加命名空间名称和作用域变量符。
  • 使用using引入命名空间的某个成员。
  • 使用using namespace 命名空间名称 引入。
using namespace std;//C++库中所有的东西都是放在std命名空间里的namespace N1
{int a = 10;int b = 20;int func(int a, int b){return a + b;}
}using N1::b;
int main()
{printf("%d\n", N1::a);printf("%d\n", b);return 0;
}

关于命名空间std:C++库中所有的东西都是放在std命名空间里的


二、输入输出

  1.  使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时,必须包含< iostream >头文件以及按命名空间使用方法使用std。
  2. cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,他们都包含在包含<iostream >头文件中。
  3.  <<是流插入运算符,>>是流提取运算符
  4. 使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式。C++的输入输出可以自动识别变量类型
  5. 实际上cout和cin分别是ostream和istream类型的对象,>>和<<也涉及运算符重载等知识,
//在日常练习中,不在乎和库命名冲突,可以直接用std命名空间
//在日后项目开发中:
//可以用std::cout,每次使用都要加std:: 用起来麻烦
//也可以把常用一些对象和类型展出来:
//工程中比较推荐这样
using std::cout;
using std::endl;
using std::cin;
//cout和cin
//与printf和scanf最大的区别:能够自动识别类型
int main()
{std::cout << "hello world!" << std::endl;int i = 1;double d = 1.11;std::cout << i << " " << d << std::endl;
}

三、缺省参数

          缺省参数声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。

void Func(int a = 0)
{cout << a << endl;
}int main()
{Func(10);   //输出10Func();		//输出0return 0;
}
全缺省
//全缺省:
//有四种调用方式:(必须从左往右传入参数)
// 不传参数	
// 只传入部分参数
// 传入全部参数
void Func(int a = 10, int b = 20, int c = 30)
{cout << "a=" << a << endl;cout << "b=" << b << endl;cout << "c=" << c << endl;
}
半缺省
//半缺省:(缺省部分参数)
//半缺省必须是从左往右缺省,不能间隔着给
void Func2(int a, int b = 20, int c = 30)
{cout << "a=" << a << endl;cout << "b=" << b << endl;cout << "c=" << c << endl;
}

 缺省参数传参必须从左往右传参


四、函数重载

     1、函数重载

        函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数、类型、类型顺序)不同,常用来处理实现功能类似数据类型
不同的问题。

  • 仅有返回值不同,不能构成重载
//函数重载:函数参数顺序不同、参数类型不同、参数类型不同
int Add(int left, int right)
{return left + right;
}
double Add(double left, double right)
{return left + right;
}
long Add(long left, long right)
{return left + right;
}
2、重载的原因

3、以Linux下的C++函数名修饰规则为例(Windows下的规则过于复杂):

        通过下面我们可以看出gccC语言编译器)的函数修饰后名字不变。而g++(C++编译器的函数修饰后变成【_Z+函数长度+函数名+类型首字母】。

(Windows的函数名修饰规则请读着自行查阅)

  • gcc编译

  • g++编译。 

 4、extern "C"

要求C和C++都能够使用C++的库(静态库/动态库)。

extern  "C" void* tcmalioc(size_t n);
//extern "C"
//表示按C语言的修饰规则,到符号表找该函数

五、引用

1、引用
  • 引用不是定义一个新的变量,而是给已存在变量取了一个别名
  • 编译器不会为引用变量开辟内存空间,它和它引用的变量公用一块内存空间
2、性质
  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用, 引用一旦引用一个实体,再不能引用其他实体。

3、常引用

”引用,即const修饰的引用。

 关于指针的权限:

int main() {const int a = 10;// int& b=a;// 权限放大:const不能给非const,const只能给constconst int& b = a;int c = 20;// 权限缩小:非const能给非const,也可以给constint& d = c;const int& e = c;const int* pa = &a;// int* pa=&a;  //编译不通过,属于权限的放大int* pc1 = &c;const int* pc2 = &c; // 编译通过,属于权限的缩小
}
4、引用和指针
  •  在语法概念引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。
  • 底层实现上实际是有空间的,因为引用是按照指针方式来实现的。

 引用和指针的不同点:

  1. 引用是定义一个变量的别名,指针存储一个变量的地址。
  2. 引用在使用时必须初始化,指针没有要求。
  3. 引用在初始化一个实体后,不能在引用其他实体,而指针可以在任何时候指向任意一个同类型的实体。
  4. 没有NULL引用,但是有NULL指针
  5. 在sizeof中含义不同:引用的结果是引用类型的大小,而指针始终是地址空间所占字节个数(32位平台x86占4个字节)。
  6. 引用自增即引用的实体增加1,指针自增即指针向后移动一个类型的大小。
  7. 有多级指针,但没有多级引用。
  8. 访问方式不同,指针需要显示解引用,引用编译器自动处理
  9. 引用相比于指针更加安全
5、使用场景

        能用引用的场景,指针都可以使用,但是指针学习的成本比较高,因此许多面向对象的语言(Java等)不在使用指针。

(1)引用做参数

  • 引用做参数可以作为输出型参数
  • 提高效率。

(2)引用做返回值 

  • 提高效率。
  • 亦可以作为某一种参数,待补充……。
int Count1()
{static int n = 0;n++;return n;
}int& Count2()
{static int n = 0;n++;return n;
}
//static控制生命周期:局部变量出了作用域,不销毁(n没有了,但是存储的值还在)。
int main()
{const int& r1 = Count1();//int & r1=Count1(); //编译不通过,原因是:传值返回,返回的是这片空间的一个拷贝int& r2 = Count2();//编译通过,原因是:引用返回,返回的是n的别名,还是原来的那片空间//cout << n << endl;//编译不通过,n已经没有了,但是原来的空间还在。
}

为什么要用引用返回? 

 六、内联函数

       1、 以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率。

        内联函数适用于代码比较短,又被频繁调用的函数

        2、对于递归、代码特别长的函数,不适用于内联函数,inline只是对编译器的一个建议,因此当代码被inline修饰但不适用内敛时,编译器不会展开内联函数。(编译器有决定权)。

        3、inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。

inline void Swap(int& x1, int& x2)
{int tmp = x1;x1 = x2;x2 = tmp;
}
//频繁调用Swap,调用函数需要建立栈帧,是有消耗的
//如何解决:1、C语言使用宏函数 2、C++使用内联函数int main()
{int a = 0;int b = 1;Swap(a, b);return 0;
}

        4、如果在上述函数前增加inline关键字将其改成内联函数,在编译期间编译器会用函数体替换函数的调用。
查看方式:
1. 在release模式下,查看编译器生成的汇编代码中是否存在call Add。
2. 在debug模式下,需要对编译器进行设置,否则不会展开。

 内联函数和宏

宏的优点:

1、增强代码的复用性。

2、提高效率。

宏的缺点:

1、宏不能被调试(预编译截断被全部替换了)。

2、导致代码的可读性变差、可维护性变差。

3、没有类型安全的检查。

C++中哪些技术可以替换宏?

1、const 修饰对象替换宏定义。

2、inline 修饰函数替换宏函数。

七、关键字auto 

1、auto
  • 使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。
  • 因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型。
int main()
{int a = 0;auto b = a;//b的类型是根据a推导出来的int& c = a;auto& d = a;auto* e = &a;auto f = &a;cout << typeid(a).name() << endl;cout << typeid(b).name() << endl;cout << typeid(c).name() << endl;cout << typeid(d).name() << endl;cout << typeid(e).name() << endl;cout << typeid(f).name() << endl;return 0;
}
2、注意
  • auto不能作为函数参数。
  • auto不能直接用来声明数组。
  • auto常与范围for搭配使用。

八、范围for

int main()
{int array[] = {1,2,3,4,5};for (auto& i : array){//引用类型才能改变array元素的值i *= 2;}for (auto i : array){cout << i << endl;}
}
  • for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。
  • 与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环。

 for循环迭代的范围必须是确定的:

  1. 对于数组而言,就是数组中第一个元素和最后一个元素的范围;
  2. 对于类而言,应该提供begin和end的方法,begin和end就是for循环迭代的范围。

九、指针空值

指针空值:nullptr。nullptr==(void*) 0

  1.  在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。
  2.  在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。
  3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。

http://www.ppmy.cn/news/1556007.html

相关文章

[Effective C++]条款33 继承, 重载与作用域

本文初发于 “天目中云的小站”&#xff0c;同步转载于此。 条款33 : 避免遮掩继承而来的名称 本条款并非和继承有关, 而是在讨论由继承引发的作用域问题, 其有可能破坏条款32所确定的法则, 因此我们在其之后介绍本条款。 我们知道在不同作用域下如果有相同名称的事物, 无论其功…

海康威视监控web实时预览解决方案

海康威视摄像头都试rtsp流&#xff0c;web页面无法加载播放&#xff0c;所以就得转换成web页面可以播放的hls、rtmp等数据流来播放。 一&#xff1a;萤石云 使用萤石云平台&#xff0c;把rtsp转化成ezopen协议&#xff0c;然后使用组件UIKit 最佳实践 萤石开放平台API文档 …

使用 imageio 库轻松处理图像与视频

使用 imageio 库轻松处理图像与视频 imageio 是一个 Python 库&#xff0c;用于读取和写入多种图像和视频格式。它功能强大、易于使用&#xff0c;广泛应用于图像处理、视频编辑和数据可视化等领域。本篇文章将介绍 imageio 的基础功能、常见用法以及高级操作。 一、安装 imag…

亚远景-ASPICE实施策略:构建高效汽车软件质量保证体系

ASPICE&#xff08;Automotive SPICE&#xff09;是一个针对汽车行业软件过程改进的国际标准&#xff0c;它旨在提高汽车软件的质量和可靠性。实施ASPICE通常需要一个系统性的策略&#xff0c;以下是一些关键的步骤和策略&#xff1a; 一、了解ASPICE 基本概念与要求&#xff…

智能家居WTR096-16S录放音芯片方案,实现语音播报提示及录音留言功能

前言&#xff1a; 在当今社会的高速运转之下&#xff0c;夜幕低垂之时&#xff0c;许多辛勤工作的父母尚未归家。对于肩负家庭责任的他们而言&#xff0c;确保孩童按时用餐与居家安全成为心头大事。此时&#xff0c;家居留言录音提示功能应运而生&#xff0c;恰似家中的一位无形…

鸿蒙NEXT开发案例:九宫格随机

【引言】 在鸿蒙NEXT开发中&#xff0c;九宫格抽奖是一个常见且有趣的应用场景。通过九宫格抽奖&#xff0c;用户可以随机获得不同奖品&#xff0c;增加互动性和趣味性。本文将介绍如何使用鸿蒙开发框架实现九宫格抽奖功能&#xff0c;并通过代码解析展示实现细节。 【环境准…

AI 智能名片 S2B2C 商城小程序在社群团购运营中的作用与价值

摘要&#xff1a;本文深入探讨了 AI 智能名片 S2B2C 商城小程序在社群团购运营中的重要作用。随着社群团购的兴起&#xff0c;如何有效运营成为关键问题。AI 智能名片 S2B2C 商城小程序凭借其独特功能&#xff0c;能够在促进消费者互动、提升产品传播效果、影响购买决策以及实现…

NLP大模型学习总结

参考课程 【清华NLP】刘知远团队大模型公开课全网首发&#xff5c;带你从入门到实战-知乎 一、自然语言处理基础 1.1 自然语言处理的基本任务 让计算机理解人所说的文本 语音 词性标注&#xff1a;区分每个词名词、动词、形容词等词性命名实体的识别&#xff1a;名词的具体…