全面讲解C++

  1. 数据类型

1.1 基本数据类型

1.1.1 整型(Integer Types)

整型用于表示整数值,分为以下几种类型:

  1. int:标准整数类型,通常为4字节(32位)。
  2. short:短整型,通常为2字节(16位)。
  3. long:长整型,通常为4字节(32位)或8字节(64位),依赖于系统。
  4. long long:更长的整型,至少为8字节(64位)。

整型可以带符号(signed)或无符号(unsigned),如unsigned int表示无符号整数。

1.1.2 浮点型(Floating-Point Types)

浮点型用于表示带小数的数值,主要有:

  1. float:单精度浮点型,通常为4字节(32位)。
  2. double:双精度浮点型,通常为8字节(64位)。
  3. long double:扩展精度浮点型,通常为8字节或16字节,具体依赖于编译器和平台。

1.1.3 字符型(Character Type)

字符型用于表示单个字符,使用char类型,通常为1字节(8位)。字符型可以是带符号或无符号:

1.1.4 布尔型(Boolean Type)

布尔型用于表示逻辑值,只有两个值:true(真)和false(假)。

1.1.5 空类型(Void Type)

void类型表示无类型,常用于函数的返回类型,表示函数不返回任何值。

1.2 复杂数据类型

复杂数据类型是通过组合基本数据类型或其他复杂类型构建的,主要包括以下几种:

1.2.1 数组(Array)

数组是相同类型元素的集合,可以通过下标访问元素。数组的大小在定义时确定。

1.2.2 结构体(Structures)

结构体用于将不同类型的数据组合在一起,方便管理和传递。

1.2.3 类(Class)

类是C++的核心特性,支持封装、继承和多态,允许定义对象的属性和行为。

1.2.4 联合体(Unions)

1.2.5 枚举(Enumerations)

1.2.6 指针(Pointers)

1.2.7 字符串(Strings)

1.3 总结

C++中的数据类型包括基本数据类型和复杂数据类型。基本数据类型用于表示简单的数值和字符,复杂数据类型则通过组合基本类型形成更复杂的结构。理解这些数据类型有助于高效地管理和操作数据,编写可读性强、维护性好的代码。

  1. 数组

C++中的数组使用于存储相同类型数据的固定大小的连续集合。它可以存储基本类型(如整数、浮点数、字符等)以及用户定义的类型(如结构体、类对象等)。接下来会对这些使用方式进行详细介绍:

2.1 数组的存储方式

  1. 线性存储:数组中的元素在内存中使连续存储的,也就是说,数组的每个元素占据的内存地址是相邻的。例如,假设数组中存储的是int类型的元素(每个元素占据4个字节),如果数组第一个元素的地址为A,那么第二个元素的地址为A + 4,依此类推。
  2. 索引访问:数组的元素可以通过索引访问,索引从0开始。例如,arr[0]是数组的第一个元素,arr[1]是第一个元素。

2.2 数组的声明和初始化

在C++中,声明数组时必须指定数组的大小(静态数组)或者使用动态内存分配(动态数组)。下面将会分类介绍以下静态数组动态数组

2.2.1 静态数组

1.声明

图 2-2-1-1 静态数组声明

注意:数组的大小必须是编译时已知的整数常量。

2.初始化

数组的初始化可以通过以下几种方式:

图 2-2-1-2 静态数组的初始化

2.2.2 动态数组

在C++中也可以使用动态内存分配来创建数组,特别是数组大小在运行时才确定的情况下。

图 2-2-1-3  动态数组

注意:在动态数组的使用过程中,需要进行手动释放内存,否则会导致一些不好的事情发生,

2.3 数组的使用方法

数组的元素通过索引访问和操作,常见的操作有:

2.3.1 访问数组元素

在访问数组元素的时候可以通过索引进行访问,时间复杂度为O(1),非常快捷:

图 2-3-1-1 访问数组元素

2.3.2 修改数组元素

在修改数组元素的值的时候,也是通过索引进行访问,然后修改,和变量值的修改区别不大:

图 2-3-2-1 修改数组元素

2.3.3 遍历数组

使用for循环或while循环来遍历数组中的每个元素:

图 3-3-3-1 数组遍历

2.3.4 多维数组

C++支持多维数组,常见的多维数组为二维数组:

图 3-3-4-1 多维数组

通常情况下,我们使用最多的就是一维数组/二维数组,三维数组极少使用。

2.4 注意事项

  1. 数组越界问题

数组索引必须在合法范围之内(0~size-1),否则会造成未定义行为(UB,Undefined Behavior)。访问或修改超出范围的元素可能导致程序崩溃数据损坏

图 3-4-1-1 数组越界

  1. 数组大小固定

静态数组的大小在声明时必须指定,并且在运行时无法更改。如果需要可变大小的数组,应该考虑使用动态数组(通过new分配)或STL中的容器(如std::vector)。

  1. 数组初始化

如果在声明时未显式初始化数组,数组中的元素会包含垃圾值。因此,建议初始化数组或手动将其所有元素值设为0。

int arr[5]= {0};  // 初始化数组元素全为0

  1. 动态数组的内存管理

在使用new动态分配数组时,务必在使用完后使用delete[]释放内存。放置内存泄露。

int* arr = new int[100];

// ....一系列操作

//使用完成后

delete[] arr;

  1. 多维数组内存布局

在C++中,多维数组实际上是线性内存中的一维数组。对于一个二维数组arr[2][3],元素arr[1][2]实际上位于数组的一维地址arr[5]位置。因此在处理多为数组时要理解其内存中的线性布局。

  1. std::array 和 std::vector

现代C++标准库提供了更安全和灵活的容器类。std::array提供了静态数组的替代品,它可以进行数组边界检查。std::vector时动态大小的数组,提供了更灵活的内存管理。

图 3-4-1 array静态数组

2.5 总结

C++中的数组是一种基本的集合数据结构,提供高效的存储和访问方式。理解其内存布局,声明和初始化方法时高效使用数组的关键。在编写代码时要注意避免数组越界和内存泄露等问题。在现代C++开发的过程中,可以考虑使用STL容器(如std::vector)来代替传统数组,以获得更好的内存管理和灵活性。

3 指针和引用

C++继承于C,并对其进行了一些拓展和优化,其中最主要的就是类和对象。不过这里的讲解对象并不是它,而是指针和引用。

在最初学习指针的时候,会有很多人觉得指针比较困难,接下来会对两者进行一个简单的讲解:

C++中的指针和引用是两个重要的概念,特别是在内存管理、函数参数传递和对象操作方面起着关键作用。理解它们的区别、用法以及各自的优缺点,对编写高效的C++代码至关重要。接下来,我将详细讲解C++中的指针和引用,包括它们的定义、使用方法、区别、注意事项等。

 3.1 指针

3.1.1 指针的定义

指针也是一个变量,不过它存储的是另一个变量的内存地址。通过地址,我们可以间接地访问修改其它变量的值

  1. 指针的声明

声明指针时需要指明它所指向的变量类型,格式如下:

type* pointerName;  //type是需要声明的类型,比如说int、float等等

  1. type:指针所指向的变量类型;
  2. *:表示这是一个指针;
  3. pointerName:指针变量的名字。

3.1.2 指针的使用

指针的主要用途是通过内存地址访问和操作变量。我们可以通过赋值操作让指针指向某个变量的地址,使用 & 符号获取变量的地址。

  1. 赋值指针

图 3-1-2-1 赋值指针

  1. 访问指针指向的值

图 3-1-2-2 访问指针

  1. 修改指针指向的值

通过指针不仅可以访问变量的值,还可以修改它。

图 3-1-2-3 修改指针的值

3.1.3 常见操作

1. 指针的自增和自减

当对指针进行自增(++)或自减(--)操作时,指针的地址会根据指针类型的大小进行移动。

  1. nullptr

C++11引入了nullptr表示空指针,替代传统的NULL。

  1. 动态内存分配

使用指针可以动态分配和释放内存。

3.1.4 指针的注意事项
  1. 指针的初始化

指针在声明后应尽量立即初始化,未初始化的指针可能指向任意内存,导致未定义行为。

  1. 指针的越界访问

在访问数组或动态分配的内存时,必须确保指针不会越界访问,否则可能导致崩溃或未定义行为。

  1. 内存泄露

动态分配内存之后,如果说没有使用delete函数,可能会导致内存泄漏,尤其是在大量动态分配的场景下。

3.2 引用

3.2.1 引用的定义

引用(Reference)是变量的别名,它本质上是一个已存在变量的另一个名字(相当于小名或昵称等等)。定义引用时需要使用 & 符号。引用必须在声明时初始化,并且初始化后不能改变所绑定的对象。

  1. 引用的声明
  1. type:引用所引用的变量的类型;
  2. &“表示这是一个引用;
  3. referenceName:引用变量的名字。

3.2.2 引用的使用

通过引用,我们可以像操作原变量一样操作引用,引用总是与它引用的变量绑定在一起。引用常用于函数参数传递中,以避免传递的性能开销。

  1. 通过引用修改变量

2. 引用作为函数参数

引用常用于函数传递,避免值拷贝的开下奥,并允许在函数内部修改传入的参数。

3. 常量引用

常量引用(const引用)是指不能通过该引用修改其绑定的变量的值,常用于保护函数参数,防止修改传入的对象。

3.2.3 引用的注意事项

1. 必须初始化

引用在声明时必须立即初始化,不能指向空或未定义的变量。

2. 不能改变引用的绑定

一旦引用绑定到某个变量,无法更改其绑定对象。引用是不可重定向的。

  1. 不能指向nullptr

与指针不同,引用是不能指向nullptr或不存在的对象。

3.3 指针与引用的比较

3.4 适用场景

指针:适合动态内存管理、数组操作、需要改变指向对象的场景。指针还可以做指针算数,如遍历数组。

引用:适合参数传递、返回值优化更安全且简介,但不具备指针的灵活性。

3.5 总结

C++中的指针和引用都是强大的工具,但它们是用于不同的场景。指针能够进行灵活的内存操作,可以通过动态内存分配和指针算数高效处理数据,但需要开发者严格管理内存,避免越界访问和内存泄漏。引用相对简单,常用于函数参数传递和返回值优化。选择使用指针还是引用取决于具体需求和场景。

  1. 结构体

C++中的结构体(struct)是一种用户自定义的数据类型,允许将不同类型的数据组合在一起。结构体广泛用于组织复杂的数据,更加清晰地表示现实世界中的实体。下面会对结构体的定义、初始化、使用方法和注意事项进行讲解:

4.1 结构体的定义

4.1.1 基本语法

结构体的定义使用struct关键字,格式如下:

  1. StructName:结构体的名称;
  2. dataType:成员变量的类型。
4.1.2 示例

4.2 结构体的使用

4.2.1 声明和初始化

结构体可以声明变量并初始化:

也可以在声明时进行初始化:

4.2.2 访问结构体成员

使用点(.)访问结构体的成员

4.2.3 结构体数组

可以创建结构体的数组,以便管理多个相同类型的结构体:

4.2.4 结构体作为函数参数

结构体可以作为函数的参数进行传递,可以通过值传递或引用传递:

4.3 结构体的特点

  1. 可以包含不同类型的成员:
    结构体可以包含啊多种数据类型的成员,例如:整数、字符串、读点书等等。
  2. 可以嵌套

结构体可以包含其它结构体作为成员。

3. 默认访问权限

结构体的成员默认是public,而类的成员默认是private。

4. 可以定义构造函数

结构体可以像类一样定义构造函数、析构函数、成员函数等。

4.4 注意事项

  1. 内存对齐

结构体的内存布局可能会受到对齐规则的影响,可能导致结构体的大小比其成员的总大小大。可以使用#pragma pack指令来控制对齐方式。

  1. 比较运算符

结构体默认不支持比较运算符,如果需要比较结构体实例,需要自自定义比较函数。

  1. 拷贝构造和赋值操作

结构体支持拷贝构造和赋值操作,但在有指针成员的情况下需要特别小心,避免浅拷贝问题。

4.5 总结

C++中的结构体是一个灵活且强大的工具,能将不同类型的数据组织在一起,方便管理和使用。结构体广泛用于数据建模、游戏开发、网络编程等场景。理解结构体的定义、使用和注意事项,对于高效编写C++代码是非常重要的。

5 类和对象

C++中的类(class)和对象(object)是面向对象编程(OOP)的核心概念,允许程序员通过封装数据和功能来创建复杂的程序。以下是面对C++类和对象的详细讲解,包括定义、使用方法、特性和注意事项。

5.1 类的定义

5.1.1 基本语法

类的定义使用class关键字,格式如下:

  1. ClassName:类的名称;
  2. dataType:成员变量的数据类型;
  3. public、private、protected:访问控制符,控制成员的可见性。

5.1.2 示例

5.2 对象的创建与使用

5.2.1 创建对象

对象是类的实例,通过类定义的构造函数来初始化:

5.2.2 访问对象的成员

使用点运算符(.)访问对象的成员变量和成员函数:

5.2.3 类的数组

可以创建类对象的数组:

5.3 类的特性

5.3.1 封装

类提供了封装的特性,可以将数据和操作数据的函数绑定在一起,同时控制访问权限。通过public、private和protected来控制成员的可见性。

  1. public:可以外部访问;
  2. private:外部不可访问,仅限类内部使用;
  3. protected:外部不可访问,但是可以被派生类访问。

5.3.2 继承

C++支持继承,允许一个类(子类)从另一个类(基类)继承成员和功能:

5.3.3 多态

C++支持多态性,允许通过基类指针或引用调用子类的函数。这通常通过虚函数实现:

5.3.4 构造函数与析构函数
  1. 构造函数:用于初始化对象,可以重载;
  2. 析构函数:用于清理对象,当对象被销毁时自动调用。

5.4 注意事项

  1. 内存管理

如果类使用动态内存(如通过new分配),则应在析构函数中释放内存,放置内存泄露。

  1. 拷贝构造和赋值操作

C++自动生成的拷贝构造函数和赋值操作符执行浅拷贝,可能导致问题。需要在有指针成员的类中自定义它们。

  1. 访问控制

合理使用访问控制符,以保护类的内部数据,确保数据的有效性。

5.5 总结

C++中的类和对象是面向对象编程的基础,允许开发者通过封装、继承和多态性来设计灵活、可扩展的代码。理解类和对象的定义、使用和特性,对于高效编写C++程序至关重要。在编写复杂程序时,合理地利用类和对象可以显著提高代码的可维护性和可读性。

6 函数

6.1 函数的定义

6.1.1 基本语法

函数的定义通常包括返回类型、函数名称、参数列表和函数体:

  1. returnType:函数返回值的类型,若无返回值则使用void;
  2. functionName:函数名称,符合标志符命名规则;
  3. parameterType和parameterName:参数的数据类型和名称。

6.1.2 示例

6.2 函数的调用

6.2.1 调用函数

可以通过函数名称和参数列表调用函数:

6.3 参数传递

6.3.1 值传递

默认情况下,C++使用值传递,将实参的副本传递给函数。

6.3.2 引用传递

可以使用引用传递,允许在函数内直接修改实参的值。

6.3.3 指针传递

可以通过指针传递参数,允许在函数内修改实参:

6.4 返回值

6.4.1 返回单一值

函数可以返回一个值,使用return语句。

6.4.2 返回多个值

通过结构体、std::tuple或引用参数返回多个值。

6.5 函数重载

C++允许同一名称的函数具有不同的参数列表,称为函数重载。重载函数可以根据参数的类型和数量进行区分。

6.6 内联函数

使用inline关键字可以定义内联函数,编译器会尝试在调用出替换函数体,以提高性能。

6.7 注意事项

  1. 函数原型:在调用函数之前,可以使用函数原型声明函数的类型和参数,允许在源文件的其它位置定义函数。

2. 默认参数:可以为函数参数提供默认值,使得调用时可以省略某些参数。

3. 递归:函数可以调用自身,称为递归,需确保有终止条件以防无限递归。

6.8 总结

C++中的函数是组织代码的重要工具,支持多种参数传递方式和返回值机制。理解函数的定义、调用和特性,对于编写可维护、可重用的代码至关重要。函数重载和内联函数的使用,可以有效提高程序的灵活性和性能。

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

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

相关文章

量子数字签名概述

我们都知道,基于量子力学原理研究密钥生成和使用的学科称为量子密码学。其内容包括了量子密钥分发、量子秘密共享、量子指纹识别、量子比特承诺、量子货币、秘密通信扩展量子密钥、量子安全计算、量子数字签名、量子隐性传态等。虽然各种技术发展的状态不同&#xf…

FreeRTOS学习总结

背景:在裸机开发上,有时候我们需要等待某个信号或者需要延迟时,CPU的运算是白白浪费掉了的,CPU的利用率并不高,我们希望当一个函数在等待的时候,可以去执行其他内容,提高CPU的效率,同…

windows修改文件最后修改时间

一、需要修改日期的文件 背景:有时候我们需要做一些文件定期删除的操作,但是测试时候并不一定有符合测试的文件,这时候就需要可以方便的修改文件的最后修改时间。 系统环境:windows 测试文件:如上 修改时间方式:windows 脚本。 二、测试脚本 (1) 脚本 # 指定文件路径 …

自然语言处理:第五十三章 Ollama

代码: ollama/ollama: Get up and running with Llama 3.1, Mistral, Gemma 2, and other large language models. (github.com) 官网: Ollama 写在前面: 笔者更新不易,希望走过路过点个关注和赞,笔芯!!! 写在前面: 笔者更新不易…

Android Framework默认授予app通知使用权限

安卓通知使用权限 在安卓系统中,应用程序需要获取通知使用权限才能向用户发送通知。以下是关于安卓通知使用权限的一些信息: 权限获取方式 当用户安装应用时,系统可能会在安装过程中提示用户授予应用通知权限。用户可以选择允许或拒绝。 应…

架构设计笔记-18-安全架构设计理论与实践

知识要点 常见的安全威胁: 信息泄露:信息被泄露或透露给某个非授权的实体。破坏信息的完整性:数据被非授权地进行增删、修改或破坏而受到损失。拒绝服务:对信息或其他资源的合法访问被无条件地阻止。攻击者向服务器发送大量垃圾…

OCM认证考试须知:掌握这些关键点,轻松应对考试

在Oracle认证体系中,OCM(OracleCertifiedMaster)是最高级别的认证。它代表了在Oracle数据库技术领域的顶尖水平。 OCM认证不仅要求你具备深厚的理论知识,还要求你能够解决复杂的数据库问题,并具备高级的项目管理能力。…

数据结构期中代码注意事项(二叉树及之前)1-11

注意&#xff1a;链表为空。是否越界访问。每写一步都要思考该步是否会有越界&#xff08;多/少&#xff09;等问题。这一步是否有不能走的条件&#xff08;删除的时候不为空&#xff09;。只有该节点开辟了空间&#xff0c;该节点才能被指向。能用c就用c。#include <iostre…

TensorRT-LLM七日谈 Day4

在Day2 中&#xff0c;我们梳理了trt-llm对于TinyLLama的调用&#xff0c;在Day3,我们也熟悉了一下Trt-llm常规的三步流程。 这里其实有个问题&#xff0c;在针对tiny-llama的部署中&#xff0c;其实没有显式的进行模型转换&#xff0c;那麽其推理接口中到底包含了什么&#x…

46 C 语言文件的打开与关闭、写入与读取函数:fopen、fclose、fputc、fputs、fprintf、fgetc、fgets、fscanf

目录 1 文件的存储形式 2 打开文件——fopen() 函数 2.1 功能描述 2.2 函数原型 2.3 文件打开方式&#xff08;模式&#xff09; 3 关闭文件——fclose() 函数 3.1 功能描述 3.2 函数原型 4 常见的文件写入方式 4.1 fputc() 函数 4.1.1 功能描述 4.1.2 函数原型 4…

windows自动化(一)---windows关闭熄屏和屏保

电脑设置关闭屏幕和休眠时间不起作用解决方案 一共三个方面注意&#xff1a; 一、关闭屏保设置&#xff1a; 二、电源管理设置 三、关闭盖子不做操作&#xff1a; 第一点很重要&#xff0c;就算二三都做了&#xff0c;一没做&#xff0c;照样不行。

一篇python的pandas数据分析,分组与聚合使用!

在数据分析中,数据分组与聚合是常用的操作,能够帮助我们从大量数据中提取出有用的信息.我们讨论了描述性统计,了解了如何通过均值、方差等统计量概述数据的特征.而在本篇中,我们将学习如何对数据进行分组和聚合,以便进行更深入的分析.最后,我们将在后续的章节中使用这些分析结果…

PHP政务招商系统——高效连接共筑发展蓝图

政务招商系统——高效连接&#xff0c;共筑发展蓝图 &#x1f3db;️ 一、政务招商系统&#xff1a;开启智慧招商新篇章 在当今经济全球化的背景下&#xff0c;政务招商成为了推动地方经济发展的重要引擎。而政务招商系统的出现&#xff0c;更是为这一进程注入了新的活力。它…

ES(Elasticsearch)SSL集群部署

8.x后ES不在需要自行准备JDK环境&#xff0c;部署的服务包含ES、Kibana、Logstash&#xff0c;使用二进制方式部署&#xff0c;为了提高安全性&#xff0c;加密logstash、kibana及其他客户端到ES间的通信。 1、准备工作 1.1、 es无法使用root用户启动 useradd -m -s /bin/bas…

WebGl 使用uniform变量动态修改点的颜色

在WebGL中&#xff0c;uniform变量用于在顶点着色器和片元着色器之间传递全局状态信息&#xff0c;这些信息在渲染过程中不会随着顶点的变化而变化。uniform变量可以用来设置变换矩阵、光照参数、材料属性等。由于它们在整个渲染过程中共享&#xff0c;因此可以被所有使用该着色…

【C#网络编程】基础概念2

文章目录 网络、数据包和协议网络数据包协议TCP、UDP 地址客户端和服务器套接字 网络、数据包和协议 计算机网络通过通信通道互连的机器组成&#xff0c;通常把这些机器称为主机和路由器&#xff0c;主机是是运行应用程序&#xff08;如 Web 浏览器&#xff09;的计算机。路由器…

决战Linux操作系统

前言&#xff1a; 你是否也曾经为Linux所困扰过&#xff0c;在网上找的资料零零散散&#xff0c;是否学完Linux后还是懵懵懂懂&#xff0c;别怕&#xff0c;这篇博客是博主精心为你准备的&#xff0c;现在&#xff0c;就让我们一起来走进Linux的世界&#xff0c;决战Linux&…

一文详解数据库范式

背景 在开发中&#xff0c;我们经常需要考虑如何设计合适的表结构&#xff0c;而则往往需要考虑数据库的范式。数据库的三范式&#xff08;3NF&#xff09;是数据库设计过程中用来减少数据冗余和提高数据一致性的重要规则。它们分别是第一范式&#xff08;1NF&#xff09;、第二…

oracle数据坏块处理(一)-通过rman备份修复

表有坏块时&#xff0c;全表查询会报错&#xff1a; 这时候如果有前面正常的rman备份&#xff0c;那么我们就可以通过rman备份直接对数据文件块做恢复 先对数据文件做个逻辑检查&#xff1a; RMAN> backup check logical VALIDATE DATAFILE EXB_DATA/exb/datafile/cuteinf…

C#中Assembly3个获取路径的方法

在C#中&#xff0c;经常要获取路径 &#xff0c;可以通过Assembly的三个重载方法来获取&#xff0c;如下所示这三个分别是GetCallingAssembly、GetEntryAssembly和GetExecutingAssembly。 string tmpEntryPath Assembly.GetEntryAssembly().Location;string tmpExeasmPath As…