《Essential C++》学习笔记

《Essential C++》这本书,是适合从C选手快速过度到C++选手的 一本书,下面是个人记录

第一章:基础语法

第一章主要就是C语言基础,这里类似于表达式 数组 条件语句 循环语句,就不多概述了。

:::info
vector:可动态扩增的Array

  • Vector,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。
  • vector,是一个能够存放任意类型的动态数组,能够增加和压缩数据。

:::

第二章:面向过程的编程风格

  1. 指针和引用的区别:
    • 在本质上来说 指针和引用都是变量 存放的都是被引用对象的地址
    • 指针变量本身可以被寻址
int a =100;
int  *p= &a;//p存放的是a的地址
int **p1 = &p;//p1存放的就是p的地址
- 而引用变量地址却不可被寻址,假如引用变量为r,&r操作得到的只能是r所指向对象的地址,而不是r本身的地址。
- 数组元素允许是指针常量,而不能是引用例如 a作为一个引用数组 a[0]=1; 无法确定是a[0]的值为1还是a[0]所引用的值为1,容易产生二义性。
- 引用不能为空,而指针可以为空。你可以只声明一个指针变量,而不去给它赋值。一个未指向任何对象的指针,其地址值为0.
- 指针可以有多级,而引用只能一级
- "sizeof 引用"得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小
- <font style="color:#DF2A3F;">当我们对指针进行解引用操作时(*p),一定要确定其值并非0,对于引用来说,因为它一定会代表某个对象,所以不需要做这样的检查</font>
  1. 堆内存
    1. 堆允许程序在运行时动态地申请某个大小的内存空间。
    2. 在C++中,通过new出来的对象,需要使用delete加以释放。
  2. inline函数:用来替代C语言的宏定义
    1. inline函数可以解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题
#include <stdio.h>
//函数定义为inline即:内联函数
inline char* f(int i) {return (i % 2 > 0) ? "奇" : "偶";
} int main()
{int i = 0;for (i=1; i < 100; i++) {printf("i:%d    奇偶性:%s /n", i, f(i));    }
}
/*
普通情况运行的时候,系统通过循环要一次次调用f函数的。
使用inline之后,每次运行相当于在把printf()里的f(i)调用直接换成了return (i % 2 > 0);这样就提高了运行效率
*/

:::info

  • 也就是说,在函数体很小的情况下,使用Inline函数可以提高效率
  • 需要注意的一点是,将函数定义为inline,仅仅是对编译器的一种建议,编译器是否执行这个请求,需视编译器而定。
  • ⚠️⚠️⚠️
  • inline函数虽好,但是需要慎用
    • 内联是以代码膨胀复制为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码, 将使程序的总代码量增大,消耗更多的内存空间。
    • 如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。
    • 如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。

:::

第三章:泛型编程风格

STL部分

这部分和Java以及Kotlin里面的容器几乎差不多

  1. 顺序型容器 vector与list
    1. vector和数组类似,拥有一段连续的内存空间,并且起始地址不变。
    2. 查找效率很高,为 O(1)。但是插入和删除就比较麻烦。
    3. 而vector和java里的ArrayList一样,都具有自动扩容的功能。
    4. 不同的编译器实现的扩容方式不一样,VS2015中以1.5倍扩容,GCC以2倍扩容。
    5. list底层由双向链表实现,因此内存空间是不连续的。所以插入时间复杂度低,查找时间复杂度高。
  2. 关联容器 map和set
    1. java,里面也有类似的数据结构,map一般表示一对对的key/value组合,俗称键值对。而set就只含有key。
    2. set不允许键值重复,可以用此解决一些算法问题,例如环形链表问题。
    3. map也不允许键值重复,但是map允许修改键对应的值。set则不能修改键值。
    4. set和map底层都是红黑树,红黑树是一种具有自动平衡功能的二叉树,在set中,如果想要修改键值,那么就会破坏红黑树的结构, 所以STL中将set的迭代器设置成const,不允许修改迭代器的值。
  3. queue和stack这个和Java里面的双向链表很像,就不多说了。

Iterator(迭代器)

迭代器可以指向容器中的某个元素,通过迭代器就可以读写它指向的元素。从这一点上看,迭代器和指针类似。

vector<int> v;//声明一个int类型的可变长数组
vector<int>::iterator i;//定义一个迭代器for (i = v.begin(); i != v.end(); ++i)   //用迭代器遍历容器cout << i << " ";  //*i 就是迭代器i指向的元素

Funtion object(函数对象)

函数对象可以当成一种运算符重载。思想是:用类来封装一个函数功能,然后用这个类实例化不同的函数对象。

 class  Add {public:int operator()(int a1, int a2){//重载"( )"运算符实现加法功能return a1+a2;}
} ;int  a =1  ,b = 2 ;
Add add; //实例化add对象
cout << add(a1,a2) << endl;  

第四章:基于对象的编程风格

This指针

class Theshy  //C++代码
{
public:int num;void SetNum(int p);
};
void Theshy::SetNum(int p)
{num=  p;
}
int main()
{Theshy obj;obj.SetNum(20000);return 0;
}
struct Theshy  //C代码
{int price;
};
void SetNum(struct Theshy* this, int p) //不一样的地方 
{this->price = p;
}
int main()
{struct Theshy shy;SetNum(&shy, 20000);return 0;
}

this指针是在成员函数中用来指向其调用者(一个对象)

Static关键字

该实例归所有对象共有。
static的作用(在C/C++)

  • 修饰某个变量的时候,只初始化一次,延长了局部变量的生命周期。
  • 如修饰函数在栈空间存放的数组,不想被释放,就可以用static。

static的特点

  • 静态变量都在全局数据区分配内存
  • 未经初始化的静态全局变量会被程序自动初始化为0
  • static除了修饰成员变量之外,还可以修饰函数,叫做静态成员函数。普通成员函数可以访问所有成员(包括成员变量和成员函数),静态成员函数只能访问静态成员。
  • 被 static 修饰的变量属于类变量,可以通过类名.变量名直接引用,而不需要 new 出一个类来
  • 被 static 修饰的方法属于类方法,可以通过类名.方法名直接引用,而不需要 new 出一个类来
  • 在 C++ 中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用。所以在所有对象中都可以共享它。使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。
  • static除了修饰成员变量之外,还可以修饰函数,叫做静态成员函数。普通成员函数可以访问所有成员(包括成员变量和成员函数),静态成员函数只能访问静态成员。
#include <iostream>
using namespace std;
class Shop
{
public:Shop(int size);void ShowSize();static void ShowPrice(); //声明静态成员函数用来显示价格static int ChangePrice(int price); //声明静态成员函数用来更改价格
private:int m_size; //声明一个私有成员变量static int m_price; //声明一个私有静态成员变量
};
Shop::Shop(int size)
{m_size = size;
}void Shop::ShowSize()
{cout << "商品数量:" << m_size << endl;
}
void Shop::ShowPrice()
{cout << "商品价格:" << m_price << endl;
}
int Shop::ChangePrice(int price)
{m_price = price;return m_price;
}
int Shop::m_price = 100; //初始化静态成员变量int main(int argc, char* argv[])
{Shop::ShowPrice();Shop::ChangePrice(200);Shop::ShowPrice();Shop shop(50);shop.ShowSize();shop.ShowPrice();return 0;
}
  • 静态成员函数主要为了调用方便,不需要生成对象就能调用。

第五章:面对对象的编程风格

多态:允许将子类类型的指针赋值给父类类型的指针。和java类似这样实现了一个函数会根据传入参数的不同有不同的功能。

在程序编译阶段,对象还没有产生时,程序只能根据指针的类型来判断调用哪个函数,这时候都是调用的父类函数,当子类重写父类方法时 同时也是把继承自父类的虚表中对应函数的索引的函数指针从父类函数改成了自己的函数。这就造成了子类和父类对象里面的虚表内容不同。所以动态联编时 去子类 或者父类里面找虚表,调用的函数不同。这也就完成了多态。

#include<iostream>
using namespace std;classA{public:A(){};~A(){};void show(){cout<<"A"<<endl;}
};classB:public A{public:B(){};~B(){};
void show(){cout<<"B"<<endl;
}
};
int main()
{A *p=new B;p->show();return 0;
}

在这种情况下,程序会输出A。这就是静态联编的情况,如果我们在8和18行写上
virtual,程序就会输出B了。

第六章:以template(模板)进行编程

第六章整个一章讲都是模板,比如说我们要定义一个函数,这个函数可以实现多种类型数据比较大小的功能

int max(int x,int y);  
{return(x>y)?x:y ;}float max( float x,float y){
return (x>y)? x:y ;}

模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数, 从而实现了真正的代码可重用性。

以下为实现一个求最小值函数模板

#include <iostream>
using namespace std;template<class T>
T min(T x,T y)
{
return (x<y?x:y);
}
void main( )
{int a1=2,a2=10;double d1=1.5,d2=5.6;cout<< "较小整数:"<<min(n1,n2)<<endl;cout<< "较小实数:"<<min(d1,d2)<<endl;system("PAUSE");
}
  • 模板可以显著减小源代码的大小并提高代码的灵活性,而不会降低类型安全。
  • 编译器由模板自动生成函数的过程叫模板的实例化。

例如:

template<class T>
void Swap(T & x, T & y)
{T tmp = x;x = y;y = tmp;
}
//以上省略 
int n = 1, m = 2;Swap(n, m);  //编译器自动生成 void Swap (int &, int &)函数

模板调用语句可以明确指明要把类型参数实例化为哪种类型。可以用:模板名<实际类型参数1, 实际类型参数2, …>

#include <iostream>
using namespace std;
template <class T>
T In(int n)
{return 1 + n;
}
int main()
{cout << In<double>(4) / 2;return 0;
}
// 此处实例化的模板函数原型应为:double In(double);

第七章:异常处理

异常的几个关键字和JAVA是一样的,都离不开那几个。try,catch,throw。
try用来放置可能抛出异常的代码,而catch用来捕获抛出异常的代码。

  • 抛出异常代码
double division(int a, int b)
{if( b == 0 ){throw "Division by zero condition!";//用到了throw语句}return (a/b);
}
  • 捕获异常代码
try
{// 保护代码
}catch( ExceptionName e )
{// 处理 ExceptionName 异常的代码
}
  • 异常的优点:
    • 函数的返回值可以忽略,但异常不可忽略。如果程序出现异常,但是没有被捕获,程序就会终止,这多少会促使程序员开发出来的程序更健壮一点。而如果使用C语言的error宏或者函数返回值,调用者都有可能忘记检查,从而没有对错误进行处理,结果造成程序莫名其面的终止或出现错误的结果。
    • 整型返回值没有任何语义信息。而异常却包含语义信息,有时你从类名就能够体现出来。
    • 整型返回值缺乏相关的上下文信息。异常作为一个类,可以拥有自己的成员,这些成员就可以传递足够的信息。
    • 异常处理可以在调用跳级。这是一个代码编写时的问题:假设在有多个函数的调用栈中出现了某个错误,使用整型返回码要求你在每一级函数中都要进行处理。而使用异常处理的栈展开机制,只需要在一处进行处理就可以了,不需要每级函数都处理。
  • 异常需要的几个注意点:
    • 如果异常抛出是用的 int 类型 而在外部捕获中 捕获函数是用的char类型进行的捕获那么,该错误就不会被捕获到,而代码也就此终止异常继续往外传。
    • 性能问题。这个一般不会成为瓶颈,但是如果你编写的是高性能或者实时性要求比较强的软件,就需要考虑了。
    • 指针和动态分配导致的内存回收问题:在C++中,不会自动回收动态分配的内存,如果遇到异常就需要考虑是否正确的回收了内存。在java中,就基本不需要考虑这个。
    • 函数的异常抛出列表:java中是如果一个函数没有在异常抛出列表中显式指定要抛出的异常,就不允许抛出;可是在C++中是如果你没有在函数的异常抛出列表指定要抛出的异常,意味着你可以抛出任何异常。
    • C++中编译时不会检查函数的异常抛出列表。这意味着你在编写C++程序时,如果在函数中抛出了没有在异常抛出列表中声明的异常,编译时是不会报错的。
    • 异常会导致程序的执行流乱跳,并且非常的混乱,并且是运行时出错抛异常就会乱跳。这会导致我们跟 踪调试时以及分析程序时,比较困难。

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

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

相关文章

Django+websocket实现一个简单聊天

WebSocket是一种在单个TCP连接上进行全双工通信的协议。它由IETF在2011年定为标准RFC 6455&#xff0c;并由RFC7936补充规范&#xff0c;同时WebSocket API也被W3C定为标准。 1、定义与原理 WebSocket是独立的、创建在TCP上的协议&#xff0c;它使用HTTP/1.1协议的101状态码进…

Unreal5从入门到精通之如何解决在VR项目在头显中卡顿的问题

前言 以前我们使用Unity开发VR,Unity提供了非常便利的插件和工具来做VR。但是由于Unity的渲染效果不如Unreal,现在我们改用Unreal来做VR了,所有的VR相关的配置和操作都要重新学习。 今天就来总结一下,我在开发VR过程中碰到的所有问题。 1.编辑器,以VR运行 默认运行方式…

Python毕业设计选题:基于django+vue的宠物寄养平台的设计与实现

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 1. 前台系统功能模块 系统首页界面 用户注册界面 用户登录界面 宠物商城界面 宠物店…

LeetCode题练习与总结:有效的完全平方数--367

一、题目描述 给你一个正整数 num 。如果 num 是一个完全平方数&#xff0c;则返回 true &#xff0c;否则返回 false 。 完全平方数 是一个可以写成某个整数的平方的整数。换句话说&#xff0c;它可以写成某个整数和自身的乘积。 不能使用任何内置的库函数&#xff0c;如 …

第三届北京国际水利科技博览会将于25年3月在国家会议中心召开

由中国农业节水和农村供水技术协会、北京水利学会、振威国际会展集团等单位联合主办的第三届北京国际水利科技博览会暨供水技术与设备展&#xff08;北京水利展&#xff09;将于2025年3月31日至4月2日在北京•国家会议中心举办&#xff01; 博览会以“新制造、新服务、新业态”…

使用web.dev提供的工具实现浏览器消息推送服务

文章目录 前言实现工具和效果实现原理实现过程前端接收用户订阅请求将用户订阅信息更新到后端后端实现接收并保存订阅信息的接口后端实现消息推送的逻辑前言 对于电商独立站来说,新品上架或者促销活动上线及时通知到用户是很重要的,通知的渠道有很多,其中就包括浏览器消息推…

掌握AI Prompt的艺术:如何有效引导智能助手

开头叙述&#xff1a; 在人工智能的世界里&#xff0c;Prompt&#xff08;提示&#xff09;是沟通人类意图与机器理解之间的桥梁。它不仅是一串简单的文字&#xff0c;而是一把钥匙&#xff0c;能够解锁AI模型的潜力&#xff0c;引导它们执行复杂的任务。本文将探讨Prompt的重…

[MySQL]DQL查询语句的执行顺序

在MySQL的查询语句中&#xff0c;各个关键字的编写顺序为 1:SELECT 字段列表 2:FROM 表名 3:WHERE 条件 4:GROUP BY 分组字段列表 5:HAVING 分组后条件列表 6:ORDER BY 排序条件 7:LIMIT 分页条件 执行顺序并非像编写时的顺序一致: 1:FROM 表名 2:WHERE 条件 3:GROUP BY 分组…

ElementUI el-table 多选以及点击某一行的任意位置就勾选上

1. 需求 在el-table中&#xff0c;需要实现多选功能&#xff0c;并且点击某一行的任意位置就勾选上&#xff0c;而不是点击复选框才勾选上。 2. 实现思路 在el-table中添加ref属性&#xff0c;用于获取表格实例。在el-table-column中添加type"selection"属性&…

深度学习优化器【学习率调整和梯度修正,Optimizer】

文章目录 一、学习率调整1 余弦退火&#xff08;1&#xff09;Warm up&#xff08;2&#xff09;Cosine Anneal 2 AdaGrad3 RMSprop算法4 AdaDelta算法 二、梯度估计修正1 动量法2 Nesterov加速梯度3 Adam修正的原因 4 AdamW 三、总结参考资料 在当今快速发展的人工智能领域&am…

运算符重载详解,日期类型的实现

一、运算符重载 当运算符被⽤于类类型的对象时&#xff0c;C语⾔允许我们通过运算符重载的形式指定新的含义。C规定类类型对象使⽤运算符时&#xff0c;必须转换成调⽤对应运算符重载&#xff0c;若没有对应的运算符重载&#xff0c;则会编译报错。 类中含有多种变量&#xff0…

windows 11 配置 kafka 使用SASL SCRAM-SHA-256 认证

1. 下载安装apache-zookeeper-3.9.2 配置 \conf\zoo.cfg # The number of milliseconds of each tick tickTime2000 # The number of ticks that the initial # synchronization phase can take initLimit10 # The number of ticks that can pass between # sending a requ…

什么是FUSE用户态文件系统

零. 文件系统 1. 为什么要有文件系统 文件系统是操作系统中管理文件和目录的一种机制。它提供了组织、存储、检索和更新文件的方法&#xff0c;主要如下&#xff1a; 数据组织&#xff1a;文件系统将数据组织成文件和目录&#xff0c;使用户能够更方便地管理和查找文件。每个…

HarmonyOS 5.0应用开发——音频播放组件的封装

【高心星出品】 文章目录 音频播放组件的封装开发步骤封装类代码测试代码 音频播放组件的封装 鸿蒙中提供了AVPlayer来实现音频播放的功能&#xff0c;播放的全流程包含&#xff1a;创建AVPlayer&#xff0c;设置播放资源&#xff0c;设置播放参数&#xff08;音量/倍速/焦点模…

(10)文件操作

1. 文件指针的概念和定义 在 C 语言中&#xff0c;文件指针是一种特殊的指针&#xff0c;用于指向一个文件结构体。这个结构体包含了文件的各种信息&#xff0c;如文件名、文件状态、当前文件位置指针等。通过文件指针&#xff0c;程序可以对文件进行各种操作。 文件指针的定…

KPRCB结构之ReadySummary和DispatcherReadyListHead

ReadySummary: Uint4B DispatcherReadyListHead : [32] _LIST_ENTRY 请参考 _KTHREAD *__fastcall KiSelectReadyThread(ULONG LowPriority, _KPRCB *Prcb)

【染色时间】

题目 代码 #include <bits/stdc.h> using namespace std; #define x first #define y second typedef pair<int,int> PII; const int N 510; int dx[] {0,0,-1,1}, dy[] {-1,1,0,0}; int d[N][N], w[N][N]; int n, m; void bfs() {memset(d, 0x3f, sizeof d);q…

了解神经网络中的激活函数

一、激活函数的特征 非线性&#xff0c;激活函数必须是非线性函数。可微性&#xff0c;训练网络模型时&#xff0c;基于梯度的模型最优化方法要求激活函数必须是可导的。单调性&#xff0c;单调递增或单调递减&#xff0c;单调函数保证模型的简单。隐藏层一般需要使用激活函数…

Apache Dubbo (RPC框架)

本文参考官方文档&#xff1a;Apache Dubbo 1. Dubbo 简介与核心功能 Apache Dubbo 是一个高性能、轻量级的开源Java RPC框架&#xff0c;用于快速开发高性能的服务。它提供了服务的注册、发现、调用、监控等核心功能&#xff0c;以及负载均衡、流量控制、服务降级等高级功能。…

利用钉钉与金蝶云星空进行付款单自动化集成

钉钉数据集成到金蝶云星空&#xff1a;付款申请单下推生成付款单的技术实现 在企业日常运营中&#xff0c;数据的高效流转和准确处理是业务顺利进行的关键。本文将分享一个具体的系统对接集成案例&#xff1a;如何将钉钉平台上的付款申请单&#xff0c;通过轻易云数据集成平台…