C++书籍 第一部分专业C++程序设计概述

1,必不可少的“hello world”

#include<iostream>int main(int argc, char** argv) {std::cout << "hello world" << std::endl;return 0;
}

这个是一个极其简单的程序,虽然没有多大简直,但是可以体现c++程序格式方面的一些重要概念

2,预编译指令 

要构建一个c++程序,这个过程可以分为四个步骤,预处理,编译,汇编,链接,走完着四个过程可以构成一个应用,这四个如果有c语言基础应该都知道,如果没有那就去看我的文章程序的环境和预处理

#              表示交于预处理器处理的指令,以这个打头

include    表示指出预处理要取得这个文件中的所有的内容,并使之对当前文件可用

在C中,所包含的文件通常以.h结尾,如<stdio.h>。在C++中,标准库头文件的后缀可以忽略不要,如<iostream>。C中常用的一些标准头文件在C++中仍然存在,不过文件名可能有所不同。例如,通过包含<cstdio>,可以访问<stdio.h>中的功能

常见的预处理指令

第一个和第二个真的是再常见不过了学习c语言的时候

第三个就是预编译指令,相当于我们学习的if,else if,else这三个

最后一个#pragma在C++中一般是用来调整内存对齐,设置编译器的警告级别或者启用一些编译器特有的优化选线那个,比如你自己编写的头文件只可以插入一次就写,#pragma once 这样的指令

3,main函数

顾名思义就是整个函数的入口 

4,I/O流

如果你刚开始接触C++,并且有C的背景,很可能不清楚std::cout是什么,不明白为什么这里不用原先值得信赖的 printf()。尽管在C++用 printf()也是可以的,但是C++流库提供的输人/输出工其相
比之下要好得多

不过输出的基本思想相当简单。可以把输出流看作是数据的一个清洗槽。你扔到这个“槽”里的所有东西都会得到适当的输出。std::cout就是对应用户控制台(即标准输出,standard out)的“槽”。除此之外,还有其他的一些槽,如 std::cert、它会输出至错误控制台“<<”操作符就是把数据扔到槽里。在上述例子中,则是把一个加引号的文本串发送至标准输出。基于输出流,允许在一行代码上向流中顺序地发送多种不同类型的数据。以下代码就会输出一个文本,其后是一个数字,再后面又有另一个文本。


std::cout<<"There are"<< 219<<"ways I love you."<< std::endl;
std::endl表示-个行尾字符。输出流遇到std::endl时,它会将到目前为止发送到槽中的所有内容统统输出,并移至下一行。还有…种方法可表示行尾,即使用'\n’字符。\n字符是一个转义字符(escape character),它表示一个换行字符。转义字符可以用在任何加引号的文本串中。

常见的转义字符

1 \n换行

2 \r回车

3 \t跳格

4 \\反斜线字符

5 ”引号

流还可以接受一个用户的输入,为此最简单的方法就是对输入流使用“>>”操作符,std::cin输入流可以接受用户的键盘输入,用户输入可能很复杂,因为你并不知道用户会输入什么样的数据。

5,命名空间

命名空间主要是解决不同代码部分之间的命名冲突问题

例如:你在编写代码的时候,代码里面包含一个命名为foo()的函数,后来有一天,你需要使用一个第三方库,这个第三方库里面也有一个foo()函数,编译器看到foo()函数的时候,无论知道你指的是哪一个版本。一方面你无法修改第三方库的函数名,另一方面你自己的函数名也是困难重重,这个时候就需要命名空间来救援了

#include <iostream>
using namespace std;namespace LOVE {void print() {cout << "I LOVE YOU" << endl;}
}using namespace LOVE;
int main() {print();return 0;
}

这里我们调用命名空间的时候,我们可以使用LOVE::print也可以运用using namespace LOVE来声明以下,这样就可以不需要写这个LOVE::这个作用域了,直接使用print函数

6,using的用法

1,声明某个命名空间  using namespace std;

2,声明某个特定项      using std::cout;

一个源文件可以包含多个using指令,尽管这是一条捷径,但要注意不要滥用

在极端的情况下,如果通过using指令声明要使用已知的所有命名空间,实际上就会使命名空间根本无法起作用!如果用using指令使用了两个命名空间,而这两个命名空间中包含有相同的名字,那么还会导致命名冲突

需要知道你的代码是在哪个命名空间中操作,这一点也很重要,如此就能避免偶尔犯错,不至于调用了不正确的同名函数

 7,变量

未初始化为题的细节讨论

在C++中,可以在代码中的任何位置声明变量(variable),而且一旦声明,当前块中在声明行之后的任何位置都可以使用该变量。实际上,工程小组应当确定是在每个函数的开始处声明变量,还是根据需要在不定的位置上声明。声明变量时,可以不为变量提供值。这种未赋值的变量往往会有一个“半随机”的值这取决于当前内存中相应位置上恰好是什么值,而这往往会带来大量的bug。C++中,变量在声明时可以为之赋一个初始值。

这个半随机值也称为垃圾值

未初始化的值往往是显示该位置的内容,下面举两个例子

1  可能是其他变量声明周期结束之后遗留再那个地方的值

2  初始化栈的时候,初始化的ccc字母显示的是这个,如果这个不明白可以去看我的函数栈帧

自主思考的问题:为什么这个编译器不把这个栈上的值给重置,而是遗留再那里呢?

1,性能的优化:提高效率,清空内存是需要额外的开销的

2,内容的管理:栈内里面快速分配的,所以不回收,一下就会被其他的变量所占据,为了提高性能就没有初始化了

3,程序员的责任:为了提高程序员对待变量初始化的重要性,所以就会有了这个,避免使用未初始化的变量

 

8,短路逻辑

C++在计算表达式时使用一种“短路逻辑”(short-circuit logic)。这说明,一旦能够确定最后结果,表达式中的余下部分就不必再计算了。例如,在做以下多个布尔表达式的逻辑或操作时,只要发现其中一个布尔表达式为true,就可以确定结果肯定为true。那么余下的布尔表达式就根本不需要检查了

短路逻辑问题代码1:

#include <iostream>bool foo() {std::cout << "foo() is called" << std::endl;return true;
}int main() {bool x = false;if (x && foo()) {  // foo() 不会被调用,因为 x 为 false,短路std::cout << "Inside if block" << std::endl;}else {std::cout << "Inside else block" << std::endl;}return 0;
}

这里可以看出foo()函数并没有执行,所以可以看出这个短路逻辑,这里直接执行了这个else的语句

 

 

9,C++风格的字符串 

在C语言中有这样表示字符串的

char arraystring[20] = "hello world";
char* pointerstring = "hello world";

第一个是用数组装这个字符串

第二个是把字符串存储到只读数据段,然后用这个指针指向那个字符串

放到栈上和堆上的各个优点:(对象)

放到栈上,就是生命周期短,但是很方便清理,编译器会自动清除

放到堆上,就是生命周期长,但是不方便清理,需要自己手动清除

C++风格字符串

在C++中可以不需要用strcat()连接两个字符串,可以用+来连接字符串,然后可以用==来比较着两个字符串,对比两个内容,但是C语言中是比较他们的地址 

 

10,引用

大多数函数都有一个共同的模式,它们会取0个或多个参数,完成某些计算,并返回一个结果。不过,有时也可能打破这种模式。你可能想要返回两个值,或者希望函数能够改变传人的某个参数的值。在C中,要达到这样一些目的,主要的做法就是传入变量的指针,而不是传人变量自身。这种方法惟一的缺陷在于,对于原本很简单的任务,可能会因此引入繁杂的指针语法。

在C++中,对“按引用传递”(即传引用)有一个明确的机制。如果对一个类型附加了&,这就表示该变量是一个引用。仍然会把它当常规的变量来使用,不过就其本质而言,它实际上是原变量的一个指针。以下是一个addOne()函数的两种实现。 

void addone(int i){
i++;//Has no real effect because this is a copy of the original}
void addone(int& i){
i++;//ctually changes the original variable}

 这个引用就类似于指针了,不会创建新的副本,而是对于原有的进行改动,但是这个是常量指针,所以有更好的安全性,不可以改变方向,但是可以改变值

 

11,异常

异常是一个类,是指在程序运行时,过程中发生的一些异常的事件,比如:数组下标溢出,除0溢出,所要读的文件不存在

C语言中的异常是通过返回值来决定异常的,返回值为0就是成功,返回值为1就是异常,但是这个利用率很低,因为函数的返回值是可以忽略的,然而在C++里面,异常是不可以被忽略的,因为忽略异常代表程序结束

整形的返回值是没有任何语义信息的,但是异常的返回值是由信息的,因为可以从你的类名就可以体现出来

异常的语法:

1,try{     }这个是用来装载一切异常的抛出的

2,throw()这个是用来抛出异常值        catch()这个是用来接受异常值

catch(类型名    异常值)只有当异常值和类型名都是一致的才可以进行捕捉 

 12,面向对象的程序(员工程序)

员工的头文件

#pragma once
#include<iostream>
using namespace std;
const int kDefaultStartingSalary = 10000;
namespace Records {class Employee {public:Employee();void promote(int inRaiseAmount = 1000);           //给员工加薪水void demote(int inDemeritAmount = 1000);          //给员工降薪水void hire();                                      //雇佣或者再次雇佣人员void fire();                                      //解雇人员void display();                                   //输出人员的信息到控制台//访问和设置器(accessors 和 setters)void   setFirstName(string inFirstName);           //设置员工的名字string getFirstName();                              //获得员工的名字void   setLastName(string inLastName);             //设置员工的姓氏string getLastName();                              //获得员工的姓氏void   setEmployeeNumber(int inEmployeeNumber);    //设置员工的编号int    getEmployeeNumber();                        //获得员工的编号void   setSalary(int inNewSalary);                 //设置员工的薪水int    getSalary();                                //获得员工的薪水bool   getIsHired();                               //检查员工是否被解雇private:string mFirstName;string mLastName;int    mEmployeeNumber;int    mSalary;bool   fHired;};
}

介绍

这个是对于员工的薪水,名字,编号,是否解雇的设置与获取

                  员工的增加与下降薪水,雇佣和解雇人员,输出信息到控制台

注意点

1,命名空间头文件的声明

这里因为我们后面要把这个类放到这个命名空间里面,为了放置于其他的函数名字冲突,我们在头文件的时候就需要写下这个namespace才可以,要不然后面我们在源程序把这些函数写道这个命名空间里面不行,因为会找不到

2,常量

一开始的常量是员工的初始工资

 员工的源程序

#include"Employee.h"
namespace Records {Employee::Employee() {mFirstName = " ";mLastName = " ";mEmployeeNumber = -1;mSalary = kDefaultStartingSalary;fHired = false;}//加薪水void Employee::promote(int inRaiseAmount) {setSalary(getSalary() + inRaiseAmount);}//降薪水void Employee::demote(int inDemeritAmount) {setSalary(getSalary() - inDemeritAmount);}//雇佣或者再次雇佣人员void Employee::hire() {fHired = true;}//解雇人员void Employee::fire() {fHired = false;}//控制台void Employee::display() {cout << "Employee: " << getLastName() << ", " << getFirstName() << endl;cout << "-------------------------------" << endl;cout << (fHired ? "Current Employee" : "Former Employee") << endl;cout << "Salary: $" << getSalary() << endl;cout << endl;}//访问和设置器(accessors 和 setters)//设置员工的名字void Employee::setFirstName(string inFireName) {mFirstName = inFireName;}//获得员工的名字string Employee::getFirstName() {return mFirstName;}//设置员工的姓氏void Employee::setLastName(string inLastName) {mLastName = inLastName;}//获得员工的姓氏string Employee::getLastName() {return mLastName;}//设置员工的编号void Employee::setEmployeeNumber(int inEmployeeNumber) {mEmployeeNumber = inEmployeeNumber;}//获得员工的编号int Employee::getEmployeeNumber() {return mEmployeeNumber;}//设置员工的薪水void Employee::setSalary(int inNewSalary) {mSalary = inNewSalary;}//获得员工的薪水int Employee::getSalary() {return mSalary;}//检查员工是否被解雇bool Employee::getIsHired() {return fHired;}
}

介绍

我们这里写了这个员工的构造函数和析构函数,由于我前面没有写using namespace Employee这个指令,所以后面的函数都是需要写Employee作用域的,这里由头文件里面声明的函数的功能

函数解释

1  升降薪水

这里就是传入你所想要的升降薪水的金额,然后执行

2  雇佣和解雇人员

这个就是要依靠那个开关了,开关是打开则证明还在职,关闭则是不在了

3  名字与编号

这个就是名字的输入与使用和编号的输入与使用

4  控制台

就是打印相关的信息到控制台上面

 数据库的头文件

 

#pragma once#include"Employee.h"namespace Records {const int kMaxEmployees = 100;           //最大员工数量 const int kFirstEmployeeNumber = 1000;   //数据库需要负责自动地为新员工分配一个员工号,因此这里需要定义一个常量class Database {public:Database();~Database();//这个就是引用,把传入地对象进行放置后,// 返回地时候是返回那个那个位置地对象,而不是重新开辟一个Employee& addEmployee(string inFirstName, string inLasName);//这个函数的作用是将新员工添加到数据库中,并返回该员工对象Employee& getEmployee(int inEmployeeNumber);//根据员工编号 inEmployeeNumber 获取并返回对应的员工对象的引用Employee& getEmployee(string inFirstName, string inLastName);//根据员工的名字(inFirstName 和 inLastName)查找并返回对应员工对象的引用void  displayAll();//显示所有员工的详细信息void displayCurrent();//显示所有现在的员工的详细信息void displayFormer();//显示所有已经解雇的员工的详细信息。protected:Employee mEmployees[kMaxEmployees];//用于存储所有员工的 Employee 对象int mNextSlot;//表示下一个可用的员工槽(在 mEmployees 数组中的索引)。它跟踪下一个空的数组位置int mNextEmployeeNumber;//为每个新添加的员工分配的下一个员工编号。};
}

介绍

这里写了构造函数和析构函数用于初始化和清除

还有一些功能函数

增加员工:需要输入他的名字

得到员工:有两种:1  员工的编号  2  员工的名字

展示信息:有三种:1  展示全部的员工  2  展示在职的员工  3  展示离职的员工

变量

1  员工数组(类似于结构体数组,自定义数组)

2  下一个员工槽

3  员工编号(这里的员工编号我们初始化为1000,然后后面加数字就好了)

注意

这里的函数的返回值选择的是引用

因为我们选择引用就类似于指针一般,这样就可以不需要创建额外的副本来整这个变量,这样就可以减少开销了

数据库的源文件

#include"Database.h"
#include"Employee.h"
namespace Records {Database::Database() {mNextSlot = 0;mNextEmployeeNumber = kFirstEmployeeNumber;}Database::~Database() {}//按照名字添加员工Employee& Database::addEmployee(string inFirstName, string inLastName) {if (mNextSlot >= kMaxEmployees) {cerr << "data structure is no more room" << endl;throw exception();//std::exception 是 C++ 标准库中所有异常类型的基类// 它提供了一个通用的异常接口(主要是 what() 方法),但是它没有具体的错误信息或者类型// 通常情况下,我们不会直接抛出 std::exception,而是抛出其 派生类,这些派生类能够提供更具体的错误信息}Employee& theEmployee = mEmployees[mNextSlot++];theEmployee.setFirstName(inFirstName);theEmployee.setLastName(inLastName);theEmployee.setEmployeeNumber(mNextEmployeeNumber++);theEmployee.hire();return theEmployee;}//通过工号来寻找员工Employee& Database::getEmployee(int inEmployeeNumber) {for (int i = 0;i < mNextSlot;i++) {if (mEmployees[i].getEmployeeNumber() == inEmployeeNumber) {return mEmployees[i];}}cerr << "No employee with employee number " << inEmployeeNumber << endl;throw exception();}//按照员工地名字来寻找员工Employee& Database::getEmployee(string inFirstName, string inLastName) {for (int i = 0;i < mNextSlot;i++) {if (mEmployees[i].getFirstName() == inFirstName&& mEmployees[i].getLastName() == inLastName) {return mEmployees[i];}}cerr << "No match with name" << inFirstName << " " << inLastName << endl;throw exception();}//显示所有地员工void Database::displayAll() {for (int i = 0;i < mNextSlot;i++) {mEmployees[i].display();}}//显示现在所有地void Database::displayCurrent() {for (int i = 0;i < mNextSlot;i++) {if (mEmployees[i].getIsHired()) {mEmployees[i].display();}}}//显示之前地void Database::displayFormer() {for (int i = 0;i < mNextSlot;i++) {if (!mEmployees[i].getIsHired()) {mEmployees[i].display();}}}
}

函数的介绍:

构造函数初始化,析构函数为空

功能函数

分别为,添加员工,获得员工信息,显示自己想要条件的全部员工

显示自己想要条件的员工

利用解雇的开关的开启和关闭来设置条件就好了,全部都不需要这个条件

添加员工

就是利用mNextSlot来索引数组就好了

寻找员工

利用输入的数据和数组里面的数据进行对比寻找

用户界面源文件

#include<stdexcept>
#include<iostream>
#include "Database.h"
#include"Employee.h"using namespace std;
using namespace Records;int displaymeau();
void doHire(Database& inDB);
void doFire(Database& inDB);
void doPromote(Database& inDB);int main() {Database employeeDB;bool done = false;while (!done) {int selection = displaymeau();switch (selection) {case 1:doHire(employeeDB);break;case 2:doFire(employeeDB);break;case 3:doPromote(employeeDB);break;case 4:employeeDB.displayAll();break;case 5:employeeDB.displayCurrent();break;case 6:employeeDB.displayFormer();break;case 0:done = true;break;default:cerr << "Unkonwn commend" << endl;}}
}int displaymeau() {int selection;cout << endl;cout << "Employee Database" << endl;cout << "-------------------------" << endl;cout << "1)Hire a new employee" << endl;cout << "2)Fire an employee" << endl;cout << "3)Promote an employee" << endl;cout << "4)List all employees" << endl;cout << "5)List all current employees" << endl;cout << "6)List all previous employees" << endl;cout << "0)Quit" << endl;cout << endl;cout << "please input---------->" << endl;cin >> selection;return selection;
}void doHire(Database& inDB) {string firstName;string lastName;cout << "please input Firstname" << endl;cout << "------->";cin >> firstName;cout << "please input Lastname" << endl;cout << "------->";cin >> lastName;/*try 块:包围了可能抛出异常的代码。catch 块:捕获并处理异常。可以有多个 catch 块来捕获不同类型的异常。catch (...):表示捕获所有类型的异常。*//*try 块内的代码会被执行。如果在执行过程中发生异常,程序会跳到 catch 块进行处理。*//*exception 是 C++ 标准库中的一个基类类型,位于 <exception> 头文件中。它是所有异常类的基类,任何抛出的异常都可以继承自 exception 类expection()这个是构造函数,用于初始化异常的*/try {inDB.addEmployee(firstName, lastName);}catch (exception ex) {cerr << "Unable to add new employee" << endl;}
}void doFire(Database& inDB) {int employeeNumber;cout << "please input Employee number";cout << "------>";cin >> employeeNumber;try {Employee& emp = inDB.getEmployee(employeeNumber);emp.fire();//指程序已经被系统终止或异常中止cout << "Employee" << employeeNumber << "has been terminated" << endl;}catch (exception ex) {cerr << "Unable to terminate employee" << endl;}}void doPromote(Database& inDB) {int employeeNumber;int raiseAmount;cout << "Employee number" << endl;cout << "------>";cin >> employeeNumber;cout << "How much of a raise";cout << "------>";cin >> raiseAmount;try {Employee& emp = inDB.getEmployee(employeeNumber);emp.promote(raiseAmount);}catch (exception ex) {cerr << "Unable to promote employee" << endl;}
}

整体逻辑就是,员工的功能函数为一个cpp(加载站)————>数据库为一个cpp里面为整理这个员工的数据到数组里面去(整理站)————>最后利用函数把数据展现出来(展览站)

我们创建了一个数据库对象

这里的功能函数传递的参数都是引用类型,这个相当于指针,直接对首次设置的变量进行处理,可以减少副本,减少开销

void doHire(Database& inDB);
void doFire(Database& inDB);
void doPromote(Database& inDB);

这个就是传入这个引用

13,补充

异常:

try 块:包围了可能抛出异常的代码
catch 块:捕获并处理异常。可以有多个 catch 块来捕获不同类型的异常
catch (...):表示捕获所有类型的异常

try 块内的代码会被执行
如果在执行过程中发生异常,程序会跳到 catch 块进行处理


exception 是 C++ 标准库中的一个基类类型,位于 <exception> 头文件中,所以可以弄这个变量
它是所有异常类的基类,任何抛出的异常都可以继承自 exception 类
expection()这个是构造函数,用于初始化异常的

以上面的代码为例子:

try {inDB.addEmployee(firstName, lastName);
}
catch (exception ex) {cerr << "Unable to add new employee" << endl;
}

这个就是try里面看有没有抛出异常,catch里面虽然是一个ex,但是只要这个ex有值就会出现异常,所以决定权是看有没有抛出异常

注:这里不是抛出准确的异常就发生异常,而是抛出异常之后就发生异常

我们来看addEmployee里面的函数里面的代码

Employee& Database::addEmployee(string inFirstName, string inLastName) {if (mNextSlot >= kMaxEmployees) {cerr << "data structure is no more room" << endl;throw exception();//std::exception 是 C++ 标准库中所有异常类型的基类// 它提供了一个通用的异常接口(主要是 what() 方法),但是它没有具体的错误信息或者类型// 通常情况下,我们不会直接抛出 std::exception,而是抛出其 派生类,这些派生类能够提供更具体的错误信息}Employee& theEmployee = mEmployees[mNextSlot++];theEmployee.setFirstName(inFirstName);theEmployee.setLastName(inLastName);theEmployee.setEmployeeNumber(mNextEmployeeNumber++);theEmployee.hire();return theEmployee;
}

这里哟写出,如果有溢出的话就会抛出异常,这个exception是一个构造函数,这个构造函数就是初始化用的,然后让外面的catch去捕抓, exception不知道是什么异常,反正就是抛出一个异常,catch就抓住异常打印异常

这个通常自己写异常很有用

对象利用栈和堆的不同点

堆一般是自己手动释放,栈一般是编译器释放,这个可以取决一个对象的声明周期

前置声明

前置声明是解决依赖和提高效率的

依赖:需要放到对应位置

提高效率:提前告诉编译器有这个函数的存在

错误:如果有上述函数声明,但是没有与之对应的函数的话,就会报链接错误,因为字符表找不到

好习惯:函数声明一般放到头文件,函数的源代码是放到源文件

枚举优点

枚举是为了防止你跟别人合作的时候,无缘无故就把对应改了,枚举是利用数字去代替物体,这样就很具有可读性,但是除了这个优点就是防止后面有人改了这个对应关系,就比如你命令大王就是1,但是万一后面减了1为0或者别人定义大王为-1,这样项目合集的时候就会很多报错,但是枚举就可以很好的解决这个问题,它很严格为这些变量赋予了一个值域,注意枚举是从0开始赋值,如果默认的话

 

 

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

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

相关文章

VIVADO ILA IP进阶使用之任意设置ILA的采样频率

VIVADO ILA IP进阶使用之任意设置ILA的采样频率 VIVADO ILA IP和VIO IP结合使用任意设置ILA的采样频率 目录 前言 一、VIO IP的配置 二、ILA IP的配置 三、测试代码 四、测试结果 总结 前言 VIVADO中编写完程序上板测试时经常会用到viavdo自带的ILA逻辑分析仪IP核&#x…

spring @EnableAspectJAutoProxy @Aspect的使用和源码流程

目录 测试代码EnableAspectJAutoProxyAspectJAutoProxyRegistrarAnnotationAwareAspectJAutoProxyCreatororg.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors 实例化AnnotationAwareAspectJAutoProxyCreator bean "a"的代理…

【BUUCTF】[GXYCTF2019]BabySQli

进入页面如下 尝试万能密码注入 显示这个&#xff08;qyq&#xff09; 用burp suite抓包试试 发现注释处是某种编码像是base编码格式 MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5 可以使用下面这个网页在线工具很方便…

重生之我在异世界学编程之算法与数据结构:深入堆篇

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 正文一、堆的基本概念二、堆的存储表示三…

《自动驾驶与机器人中的SLAM技术》ch8:基于预积分和图优化的紧耦合 LIO 系统

目录 1 预积分 LIO 系统的经验 2 预积分图优化的顶点 3 预积分图优化的边 3.1 NDT 残差边&#xff08;观测值维度为 3 维的单元边&#xff09; 4 基于预积分和图优化 LIO 系统的实现 4.1 IMU 静止初始化 4.2 使用预积分预测 4.3 使用 IMU 预测位姿进行运动补偿 4.4 位姿配准部…

软件测试—— 接口测试(HTTP和HTTPS)

软件测试—— 接口测试&#xff08;HTTP和HTTPS&#xff09; HTTP请求方法GET特点使用场景URL结构URL组成部分URL编码总结 POST特点使用场景请求结构示例 请求标头和响应标头请求标头&#xff08;Request Headers&#xff09;示例请求标头 响应标头&#xff08;Response Header…

【Excel超实用,VLOOKUP函数,通过excel数据精准匹配,将一个excel文件的某列数据,用另一个excel文件快速填充】

1、使用背景 如下图1所示&#xff0c;1.xlsx文件&#xff0c;有两列数据&#xff0c;一列序号&#xff0c;一列内容&#xff0c; 我现在需要将第二列的内容快速完成填充&#xff0c;并且有相应的excel模板作为参照。 图1 如图2所示&#xff0c;2.xlsx是模板文件&#xff0c;序…

Transformer详解:Attention机制原理

前言 Hello&#xff0c;大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者&#xff0c;本系列文章是作者参加DataWhale2025年1月份学习赛&#xff0c;旨在讲解Transformer模型的理论和实践。&#x1f632; 本文将详细探讨Attention机制的原理…

PyTorch使用教程(14)-如何正确地选择损失函数?

在机器学习和深度学习的广阔领域中&#xff0c;损失函数&#xff08;Loss Function&#xff09;扮演着至关重要的角色。它不仅是衡量模型预测结果与实际数据之间差异的关键指标&#xff0c;还是指导模型优化方向、影响最终性能的核心要素。选择合适的损失函数&#xff0c;对于提…

P1825 [USACO11OPEN] Corn Maze S 刷题笔记

P1825 [USACO11OPEN] Corn Maze S - 洛谷 | 计算机科学教育新生态 定义状态空间 结构体 精简代码 遇到多种情况判断不要全写进check里面 分开写 传送门是大写字母 A-z 其acll码值 是 65-90 我们将传送门代表的字母-65 就可以将其值映射到 0-26 从而存下相应的传送门坐标…

01设计模式(D3_设计模式类型 - D3_行为型模式)

目录 一、模版方法模式 1. 基本介绍 2. 应用案例一&#xff1a;豆浆制作问题 需求 代码实现 模板方法模式的钩子方法 3. View的draw&#xff08;Android&#xff09; Android中View的draw方法就是使用了模板方法模式 模板方法模式在 Spring 框架应用的源码分析 知识小…

Nginx在Linux中的最小化安装方式

1. 安装依赖 需要安装的东西&#xff1a; wget​&#xff0c;方便我们下载Nginx的包。如果是在Windows下载&#xff0c;然后使用SFTP上传到服务器中&#xff0c;那么可以不安装这个软件包。gcc g​&#xff0c;Nginx是使用C/C开发的服务器&#xff0c;等一下安装会用到其中的…

nacos2.3.0 接入pgsql或其他数据库

首先尝试使用官方插件进行扩展&#xff0c;各种报错后放弃&#xff0c;不如自己修改源码吧。 一、官方解决方案 1、nocos 文档地址&#xff1a;Nacos 配置中心简介, Nacos 是什么 | Nacos 官网 2、官方解答&#xff1a;nacos支持postgresql数据库吗 | Nacos 官网 3、源码下载地…

使用 ChatGPT 生成和改进你的论文

文章目录 零、前言一、操作引导二、 生成段落或文章片段三、重写段落四、扩展内容五、生成大纲内容六、提高清晰度和精准度七、解决特定的写作挑战八、感受 零、前言 我是虚竹哥&#xff0c;目标是带十万人玩转ChatGPT。 ChatGPT 是一个非常有用的工具&#xff0c;可以帮助你…

【Elasticsearch 】 聚合分析:聚合概述

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

python matplotlib绘图,显示和保存没有标题栏和菜单栏的图像

目录 1. 使用plt.savefig保存无边框图形 2. 显示在屏幕上&#xff0c;并且去掉窗口的标题栏和工具栏 3. 通过配置 matplotlib 的 backend 和使用 Tkinter&#xff08;或其他图形库&#xff09; 方法 1&#xff1a;使用 TkAgg 后端&#xff0c;并禁用窗口的工具栏和标题栏 …

深入探索Python人脸识别技术:从原理到实践

一、引言在当今数字化时代,人脸识别技术已然成为了计算机视觉领域的璀璨明星,广泛且深入地融入到我们生活的各个角落。从门禁系统的安全守护,到金融支付的便捷认证,再到安防监控的敏锐洞察,它的身影无处不在,以其高效、精准的特性,极大地提升了我们生活的便利性与安全性…

国内汽车法规政策标准解读:GB 44495-2024《汽车整车信息安全技术要求》

目录 背景 概述 标准适用范围 汽车信息安全管理体系要求&#xff08;第5章&#xff09; 信息安全基本要求&#xff08;第6章&#xff09; 信息安全技术要求&#xff08;第7章&#xff09; ◆ 外部连接安全要求&#xff1a; ◆通信安全要求&#xff1a; ◆软件升级安全…

Arcgis Pro安装完成后启动失败的解决办法

场景 之前安装的Arcgis Pro 今天突然不能使用了&#xff0c;之前是可以使用的&#xff0c;自从系统更新了以后就出现了这个问题。 环境描述 Arcgis Pro 3.0 Windows 10 问题描述 打开Arcgis Pro&#xff0c;页面也不弹出来&#xff0c;打开任务管理器可以看到进程创建之后&…

SAP POC 项目完工进度 - 收入确认方式【工程制造行业】【新准则下工程项目收入确认】

1. SAP POC收入确认基础概念 1.1 定义与原则 SAP POC&#xff08;Percentage of Completion&#xff09;收入确认方式是一种基于项目完工进度来确认收入的方法。其核心原则是根据项目实际完成的工作量或成本投入占预计总工作量或总成本的比例&#xff0c;来确定当期应确认的收…