Advertisement

C++入门基础知识总结(2022整理)

阅读量:

一、C++入门基础知识之什么是C++?

于1982年,Bjarne Stroustrup博士在其开发出的基础之上发展出了面向对象编程的思想. 为了体现这种与传统编程模型的关系,他发明了一种新的程序语言,并命名为C++\!++. 因此,在其开发出的基础之上发展出了面向对象编程的思想,并命名为C++\!+. 这种新语言不仅继承了经典的编程方法——过程化程序设计的能力,并且拓展出了以抽象数据类型为中心的对象导向开发模式——支持多种编程范式

C++入门基础知识PDF版、C++提高教程、C++电子书籍 获取 方式如下

关注微信公众号:“ C和C加加 ” 回复关键字:“ C++ ”即可领取

二、C++入门基础知识看看C++的历史版本

C中的类及其继承关系包括基类及其继承类、public和private成员以及相关的构造函数及其析构函数。此外还涉及friend函数(即友元)、内联函数定义以及重载赋值运算符及其相关操作。

C++1.0 添加虚函数概念,函数和运算符重载,引用、常量等

C++2.0更加充分地支撑了面向对象的技术,并新增了许多功能如保护成员、多重继承以及静态/const相关的特性。在处理对象初始化方面表现出了色,在实现抽象类的同时也加强了对静态成员变量的设计能力,并加强了对常量成员函数的支持能力。

C++ 3.0 的升级版本进一步增强了其功能特性,并采用了模板机制来解决多重继承所带来的歧义性问题,并实现了相应的构造与析构功能

作为C++的第一个标准版本,在众多开发者的实践中确立了自己的地位。广大编译器普遍采用这一语言,并获得了国际标准化组织(ISO)以及美国标准化协会的高度认可。通过模板方法对C++标准库进行重构,并引入了STL(即标准模板库)。

C++03 C++标准第二个版本,语言特性无大改变,主要∶修订错误、减少多异性

在2023年9月,《C++技术报告》TR1被公布后,《C++》系列标准将正式更改名称为《C++》系列标准( Technical Report TR1)。该系列标准将从本世纪初的一个特定时间段内进行更新与修订工作。

C++11引入了多种新特性,在视觉效果上使它看起来更接近一种全新的编程语言。例如:支持的正则表达式功能、基于for_each循环范式的迭代操作能力提升、引入了自动指针管理的auto关键字、新增的标准容器库中的新容器类以及列表初始化语法等

C++14 对C++11 的增强主要包括对漏洞进行弥补以及功能优化等举措;其中特别包括支持泛型lambda 表达式的具体实现技术、引入了自动返回值类型推导机制以及对二进制字面常量的支持等

C++17 在 C++11 的基础上进行了小幅改进,并增添了许多新特性。其中 notable 新增了 static_assert() 提供了关于错误信息的可选文本, 折叠表达式被引入用于处理可变模板, 以及 if 和 switch 语句中的初始化器等细节

三、C++入门基础知识关键字

C++中总计有63个关键字:

需要注意的是:false和true虽然与布尔类型相关联,但它们并非C语言的关键字。

四、C++入门基础之C++的命名空间

在C/C++编程语言中,变量、函数和类等元素通常会广泛存在,并且它们的名称会被全局引用,在这种情况下可能会引发大量的命名冲突。

命名空间的主要作用在于实现标识符和名称的本地化处理,从而防止命名冲突或名字污染现象的发生,namespace关键字则是直接针对这些问题提出的解决方案。

请在Markdown语言中进行如下操作:首先声明一个名称,请使用关键字namespace,并在其后紧跟一个名称字符串。随后,在大括号内部放置该名称字符串。

空间的成员。

注意:一个命名空间确定了新的作用域,在该命名空间中的所有内容都被限制在其中。

注意:一个命名空间确定了新的作用域,在该命名空间中的所有内容都被限制在其中。

1、命名空间的普通定义

2、命名空间可以嵌套

在同一个工程环境中,尽管允许多个具有相同名称的命名空间存在于同一工程环境中,并非强制要求每个命名空间必须拥有唯一的名称,在编译过程中这些同名命名空间会被整合到同一公共命名空间中

它会与上面的xjt命名空间合并

五、C++入门基础命名空间的使用

显然直接打印printf的方法不可行。因为直接引用printf函数会导致其内存地址被引用,这将导致预期的行为不发生。正确的调用途径主要包括以下几种情况:

1、加命名空间名称及作用域限定符

符号::在C++中被定义为作用域限定符,在代码书写过程中我们需要按照指定的格式使用'命名空间名称::命名空间成员'的形式才能调用所需的功能模块

2、使用using namespace 命名空间名称引入

这种方案也存在一些局限性。如果我们在一个命名空间中定义了一个名为printf的变量,并且随后引入了namespace xjt命名空间,则会导致变量名称与外部函数名称冲突的问题。

为了解决这个问题,出现了第三种引入方法。

3、使用using将命名空间中的成员引入

这种方法可以防止命名的污染,因为它只引入了一部分。

六、C++入门基础知识的输入和输出

在C语言中采用 scanf 和 printf 这些标准输入输出函数,在C++语言环境中则分别使用 cin 作为标准输入设备以及 cout 作为标准输出设备。为了实现对数据的读取与显示操作,在C语言中必须包含 stdio.h 头文件;而在 C++ 环境下进行相关操作时,则必须包括 iostream 头文件以及声明 std 标准命名空间的标准库头文件。

相比C语言而言,在输入输出方面的便利性更为显著的是C++。这得益于C++在输入输出操作中无需预先设定格式要求的特点。具体来说,在具体的编程场景中,在处理整数值时通常采用%d的形式,在处理字符值时则使用%c的形式来完成相应的输入输出操作。

特别注意:end\l这一字符并非阿拉伯数字1所代表的换行符,在英文字符集中共有26个字母中的一员被称为L(大写),其作用等同于执行换行操作。

在处理cin时需要特别注意其特点。它与C语言中的gets具有相似之处,在处理输入数据时也存在差异性:当输入包含回车键时会终止;而当遇到空格、制表符或回车键时会分割输入。因此,在此处输入'hello world'时会因空格而被分割。

当我在此处录入'hello world'时,
然而由于在录入过程中出现了一个空格,
导致随后的所有内容都不会被包含进去,
最终导致arr变量中仅存储了'hello'。

七、C++入门基础知识-缺省参数

在声明或定义函数时为函数的参数设置一个默认值。当调用该函数而不提供实际参数时,则使用这个默认值;如果提供实际参数,则使用所给的实际参数。

1、全缺省

全缺省参数,即函数的全部形参都设置为缺省参数。

2、半缺省参数

注意:

半缺省参数必须从右往左依次给出,不能间隔着给。

缺省参数不能在函数声明和定义中同时出现

当同一作用域内存在声明和定义的位置,并且两者的赋值结果不一致时,则编译器将面临如何选择缺省值的难题。

缺省值必须是常量或者全局变量。

八、C++入门基础-C++函数重载

1、函数重载

在同一个作用域范围内支持对一些具有相似功能但实现细节不同的函数重定义进行声明,并要求这些函数重定义所具有的形参列表(参数个数、类型或顺序)各有不同。这种机制主要用于解决实现相同功能但针对不同类型数据的问题。

注意:若仅仅只有返回值不同,其他都相同,则不构成函数重载。

2、C++函数重载的原理

为什么C++支援函数重载,而C语言不可以了?

本次我们将回顾一些基础知识。在程序进入执行文件之前,必须经过以下步骤:首先通过预处理生成可执行代码;随后将源代码转换为目标代码;接着将机器指令转换为低级代码;最后将各模块代码整合成完整的可执行程序.

问题主要出现在汇编阶段之后的编译过程中

采用C语言编译器编译之后

采用C++编译器编译之后

总结:

_Z+函数长度+函数名+类
型首字母

_Z+函数长度+函数名+类
型首字母

_Z+函数长度+函数名+类
型首字母

本质上说,
这个问题归因于
C编译器与C++编译器对函数名称进行标识的方式存在差异。
在gcc环境下,
默认情况下,
_Z加上函数长度后跟上函数名及所属类型首字母。

这也揭示了原因在于不同类型的返回值不被视为同一个函数的特征;由于修饰规则不被返回值所改变。

3、extern “C”

在开发过程中可能会遇到将某些函数按C语言风格进行编译的情况,在这些函数前面添加extern \ "C"以通知编译器处理方式

请按照以下方式对给定的函数进行编译:依照C语言规范进行操作。例如,在Google中使用的是基于C++开发的tcmalloc项目,请问您需要完成哪些特定的功能?

通过两个接口实现功能的连接,在C项目中无法直接应用时,则采用外部调用机制解决问题

九、C++入门基础知识-引用

1、引用

避免重新定义现有变量而不是为其赋予了一个代号。编译器不需要分配独立的内存区域用于引用变量。它们共享相同的内存区域,并与被引用的原始变量共享数据内容。

类型& 引用变量名(对象名) = 引用实体;

注意:引用类型必须和引用实体是同种类型的

2、引用的特征

引用在定义时必须初始化

一个变量可以有多个引用

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

然而实际的表现却使得c的数值被赋予到了变量b中。其中变量b实际上是一个对变量a的引用。这样一来,在后续的操作中我们发现变量a的有效性降到了20

3、常引用

上文指出,在进行文献引用时,要求引用对象与被引用对象必须属于同一类别。然而仅凭此不足以确保此次引用的成功性,在此情况下还需关注是否可进行修改。

在本例中涉及的变量a、b、d均为常量这些常量无法被更改但当我们采用int&ra等方式引用变量a时此时所引用的变量a则可被修改这会导致问题出现。

那么这个引用是否正确呢?首先需要理解隐士类型提升的核心问题,在这一过程中int到double之间存在隐士类型的提升。系统会创建一个常量区来存储a类型在提升过程中的结果。因此这段代码明显存在问题,请注意以下几点:因为当进行隐士类型提升时a会被赋值为常量区中的值而常量区无法被修改;然而你使用double&ra去引用它会导致ra本身是可以被修改的。

加个const就可以解决这个问题。

请注意:将固定不变的变量赋值给允许修改的目标变量是不被允许的行为;然而,则是可以实现的一种情况。

4、引用的使用场景

引用做参数

还记得C语言中的交换函数吗?曾经学过C语言的人都记得它用于演示传递值与引用地址的概念吧?现在我们学习了变量引用的概念后发现,并不需要再使用指针变量作为参数就可以实现这一功能。其中a和b接收的是被调用函数的实参引用,在这种情况下将它们进行赋值互换可以直接实现将被调用函数的两个参数互换位置。

引用做返回值

当然引用也可以用作返回值。需要注意的是,在编写代码时应特别注意以下几点:我们返回的数据不可以使用函数内部创建的普通局部变量。这是因为这些普通局部变量在函数调用结束后会被销毁。因此,在这种情况下我们需要确保所返回的数据必须使用static修饰或者动态开辟或者全局变量等这些不会因函数调用结束而被销毁的数据类型。

不加static的后果

你是不是疑惑为什么打印的不是2而是7了?

这就更加令人费解的是,在代码中间插入一条printf语句却导致程序输出随机数值
。那么
为何会产生这种现象呢?

为什么会得到一个随机值呢?这是因为我们在编写代码时,在函数内部声明了一个局部变量(local variable)。当这个函数执行完毕后会销毁该局部变量。因此,在内存中它就会被分配到一个不确定的位置。为了避免这种情况,在引用这些局部变量作为返回值时,请将其声明为static

这时你觉得你真的懂这段代码了吗?

可能你会好奇了?为什么这儿是3了?下面来看看分析

如果你尝试用不同的方式表达,
那么这个答案会直接变为7,
原因很简单,
这与前面图片中提到的原因一致。

提示:当函数执行返回时,在脱离了函数的作用域后若未将返回的对象返还给系统,则应采用引用方式进行处理;而若对象已被系统回收,则必须采用传值的方式进行操作。这句话通常指的是以下场景:

大家都觉得这个传引用返回操作起来有点奇怪吗?我们来探讨一下它为什么会返回。

在传递值时会生成副本;而在传递引用时则无需生成副本。同样地,在函数参数传递中也会出现这种情况。

5、引用和指针的区别

在语法范畴内进行引用相当于一个别名,并不占用独立的空间而是与所引用实体共享同一个存储区域

在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。

我们来看下引用和指针的汇编代码对比

引用和指针的区别

引用在定义时必须初始化,指针没有要求。

一旦在一个初始化阶段引用某个实体之后,则不能再引用其他类型的实体。然而,在任何时候都可以通过指针指向任何一种类型的同类实体。

没有NULL引用,但有NULL指针。

在sizeof运算符中含义有所不同:其返回值代表引用对象类型所占用的内存空间大小。然而,在所有情况下,指针始终指向内存地址的空间占用数量。对于32位系统而言,每个指针占用4个字节。

引用执行自加运算等价于将对应的变量值增加1个单位;而指针执行自加运算则会导致其指向下一个内存单元。

有多级指针,但是没有多级引用。

访问实体的方式不同,指针需要显示解引用,而引用是编译器自己处理。

引用比指针使用起来相对更安全。

十、C++入门基础知识-内联函数

1、概念

具有inline修饰符的函数被称作内联函数。在C++编译过程中,在调用其内部链接位置展开代码,并且由于无压栈开销。通过这种技术实现调用功能能够显著提高程序运行效率。(例如,在某些情况下,在加粗部分可能会有疑问:这是否类似于C语言中的宏?)

在上述函数之前添加一个"inline"关键字将其转换为内联形式,在编译阶段时编译器会将被替换掉该函数的调用位置替换成其体内容

2、特性

采用空间换取时间的方式,在inline中减少了调用函数的开销。因此,代码长度长或递归的函数不适合作为内联函数。

inline作为对编译器的一个建议,在大多数情况下是合理的安排。然而,在实际应用中可能遇到一些限制条件。例如,在一个被定义为inline的函数内部代码过长或者涉及递归等情况时,在优化过程中可能会跳过这些内联的操作以避免潜在的问题。

不应将inline的声明与定义分开使用;否则会引发链接错误;原因在于inline会被展开后失去了函数地址信息;导致无法正确定位链接;因此建议避免这种做法以确保网页正常渲染

c++有哪些技术可以代替宏

常量定义 换用const

函数定义 换用内联函数

十一、auto关键字(C++11)

在过去的C/C++开发中,“auto”的作用域是:被auto修饰的变量属于具有自动存储器的作用域;然而这一特性却鲜有开发者愿意采用这一特性。

在C++11标准中,默认赋予了auto一种全新的角色:它不再充当存储类型指示符的角色(即不作为容器或临时变量的存储类型),而是由编译器在 compile 期间自动确定变量类型的new机制。其声明的变量类型由编译器在 compile 期间自动推断确定。或许单凭这句话还不够直观……我们通过具体的示例来进一步阐述其工作原理。比如,在函数参数处使用时。

复制代码
 #include<iostream>

    
  
    
 using namespace std;
    
  
    
 int TestAuto()
    
  
    
 {
    
  
    
 return 10;
    
  
    
 }
    
  
    
 int main()
    
  
    
 {
    
  
    
 int a = 10;
    
  
    
 auto b = a;
    
  
    
 auto c = 'a';
    
  
    
 auto d = TestAuto();
    
  
    
  
    
  
    
 cout << typeid(b).name() << endl; //这个地方要学到后面类的时候才可以解释,这里打印出的是类型名
    
  
    
 cout << typeid(c).name() << endl;
    
  
    
 cout << typeid(d).name() << endl;
    
  
    
  
    
  
    
 cout << a << endl;
    
  
    
 cout << b<< endl;
    
  
    
 cout << c << endl;
    
  
    
 cout << d << endl;
    
  
    
  
    
  
    
 //auto e; 无法通过编译,使用auto定义变量时必须对其进行初始化
    
  
    
 return 0;
    
  
    
 }
    
    
    
    
    代码解读

请注意,在使用auto类型的变量进行定义时,请确保在compiling stage对它进行适当的initialization(初始化),并让compiler解析相关的初始expression(表达式)以确定其实际的数据type(类型)。这表明auto并非一个明确声明数据类型的机制(mechanism),而是在数据类型的声明过程中扮演着一种placeholder role(占位符角色)。相应的编程语言解释器会在处理相关代码时自动推导出该变量的真实数据属性和行为模式。

1、auto的使用细则

auto与指针和引用结合起来使用

当使用 auto 来定义指针类型时,默认情况下 auto 和 auto* 完全相同;然而,在定义引用类型时,默认情况下需要带有 & 符号

请注意:在使用auto声明引用时需添加&符号;如果不这样做,则所生成的引用仅是与实体类型相同的普通变量,并且仅仅是为了更改引用名称的目的而存在的。

在同一行定义多个变量

当在同一行声明多个变量时,在一行内声明多个变量时,在同一行内声明多个变量时,在一行内声明多个变量时

2、auto不能推导的场景

auto做为函数的参数

auto不能直接用来声明数组

为了防止与C++98中的auto混淆,C++11仅保留了auto作为类型指示符的用法

十二、C++入门基础知识基于范围的for循环(C++11)

1、范围for的语法

在C++98中如果要遍历一个数组,可以按照以下方式进行:

对于一个具有明确范围的集合而言,在让程序员进行描述的情况下显得多余且有时还可能造成错误。因此,在C++11中解决了相关问题。

采用了基于范围的for循环结构。其后括号内的内容以冒号“:”分隔为两个部分,在编程逻辑中分别负责指定迭代过程中的变量名称以及遍历的具体范围。

注意不能写成auto,不然改变不了原数组

正确的写法

注意:与常规循环相仿,在本次循环中可运用continue指令以退出当前循环,并且还可以通过break指令跳出所有后续的循环。

2、范围for的使用条件

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

对于数组来说,则是其首元素与末元素之间的区间;
而针对类来说,则需提供begin和end这两个方法。

其中begin与end分别对应for循环中的初始值与终止值。

注意:以下代码就有问题,因为for的范围不确定

迭代的对象要实现++和==的操作。

关于迭代器这个问题,以后会讲,现在大家了解一下就可以了。

十三、C++入门基础-指针空值nullptr

1、C++98中的指针空值

在遵循良好的C/C++编程习惯时,在声明变量的同时最好为该变量设定适当的初始值;否则可能会导致不可预见的问题。例如未赋初值的指针,在这种情况下程序运行通常会遇到内存访问异常;常见的做法是为该指针分配内存空间以避免这些问题。

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

通常情况下

程序原本意图是试图以指针形式调用函数Fun(int* p),即当参数为NULL时

在C++98标准中,默认情况下字面常量0被视为一个整型数值类型;然而,在某些特定情境下它也可以被解释为无类型的指针(void*)常量。值得注意的是,默认情况下编译器会将它视为整型常量;因此,在需要以指针形式进行操作时,则必须对其进行显式转换

2、C++11中的指针空值

对于C++98中的问题,C++11引入了关键字nullptr。

当使用std::nullptr_t表示指针为空值时,无需包含头文件头,因为std::nullptr_t是C++11中引入的标准关键字.

在C++11中,sizeof(nullptr)与sizeof((void*)0)所占的字节数相同,大小都为4。

最后

C++入门基础知识PDF版、C++提高教程、C++电子书籍 获取 方式如下

关注微信公众号:“ C和C加加 ” 回复关键字:“ C++ ”即可领取

全部评论 (0)

还没有任何评论哟~