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开始赋值,如果默认的话

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

leetcode刷题记录(七十二)——146. LRU 缓存

&#xff08;一&#xff09;问题描述 146. LRU 缓存 - 力扣&#xff08;LeetCode&#xff09;146. LRU 缓存 - 请你设计并实现一个满足 LRU (最近最少使用) 缓存 [https://baike.baidu.com/item/LRU] 约束的数据结构。实现 LRUCache 类&#xff1a; * LRUCache(int capacity)…

微调时如何平衡新旧参数?

在微调预训练模型时&#xff0c;平衡新旧参数是一个重要的问题。合理地平衡新旧参数可以确保模型既保留预训练阶段学到的通用表示能力&#xff0c;又能够有效地适应特定任务。以下是一些常用的方法和技术来平衡新旧参数&#xff1a; ### 1. 学习率调整 **不同层使用不同的学习…

性能调优篇 四、JVM运行时参数

目录 一、三种JVM参数选项1、标准参数选项1&#xff09;特点2&#xff09;各种选项3&#xff09;-server 和 -client 2、-X参数选项3、-XX参数选项 二、添加JVM参数选项1、idea 如何添加jvm参数 三、常见的JVM参数选项1、打印设置的参数选项及其值2、堆、栈、方法区等内存大小设…

2024年博客之星主题创作|Android 开发:前沿技术、跨领域融合与就业技能展望

目录 引言 一、推动 Android 应用创新的核心力量 1.1 人工智能与机器学习的崛起 1.2 增强现实&#xff08;AR&#xff09;与虚拟现实&#xff08;VR&#xff09;的应用扩展 1.3 5G技术的推动 1.4 跨平台开发技术的成熟 1.4.1 React Native 1.4.2 Flutter 1.4.3 Taro …

汇编与逆向(一)-汇编工具简介

RadASM是一款著名的WIN32汇编编辑器&#xff0c;支持MASM、TASM等多种汇编编译器&#xff0c;Windows界面&#xff0c;支持语法高亮&#xff0c;自带一个资源编辑器和一个调试器。 一、汇编IDE工具&#xff1a;RadASM RadASM有内置的语言包 下载地址&#xff1a;RadASM asse…

Gin 源码概览 - 路由

本文基于gin 1.1 源码解读 https://github.com/gin-gonic/gin/archive/refs/tags/v1.1.zip 1. 注册路由 我们先来看一段gin代码&#xff0c;来看看最终得到的一颗路由树长啥样 func TestGinDocExp(t *testing.T) {engine : gin.Default()engine.GET("/api/user", f…

Linux网络序列化与反序列化

Linux网络序列化与反序列化 1. 前言 在网络通信中&#xff0c;互相通信的信息不一定都是字符串&#xff0c;往往一些结构化的信息也需要进行通信。理论上&#xff0c;只要服务器和客户端都自定义一个共同的协议&#xff0c;结构化的信息也能实现正常通信。但考虑到不同系统、…

实战经验:使用 Python 的 PyPDF 进行 PDF 操作

文章目录 1. 为什么选择 PyPDF&#xff1f;2. 安装 PyPDF3. PDF 文件的合并与拆分3.1 合并 PDF 文件3.2 拆分 PDF 文件 4. 提取 PDF 文本5. 修改 PDF 元信息6. PDF 加密与解密6.1 加密 PDF6.2 解密 PDF 7. 页面旋转与裁剪7.1 旋转页面7.2 裁剪页面 8. 实战经验总结 PDF 是一种非…

PhyCAGE:符合物理规律的图像到 3D 生成

Paper: Yan H, Zhang M, Li Y, et al. PhyCAGE: Physically Plausible Compositional 3D Asset Generation from a Single Image[J]. arXiv preprint arXiv:2411.18548, 2024. Introduction: https://wolfball.github.io/phycage/ Code: Unreleased PhyCAGE 是一种 image-to-3D…

游戏为什么失败?回顾某平庸游戏

1、上周玩了一个老鼠为主角的游戏&#xff0c;某平台喜1送的&#xff0c; 下载了很久而一直没空玩&#xff0c;大约1G&#xff0c;为了清硬盘空间而玩。 也是为了拔掉心中的一根刺&#xff0c;下载了而老是不玩总感觉不舒服。 2、老鼠造型比较写实&#xff0c;看上去就有些讨…

上位机工作感想-2024年工作总结和来年计划

随着工作年限的增增长&#xff0c;发现自己越来越不喜欢在博客里面写一些掺杂自己感想的东西了&#xff0c;或许是逐渐被工作逼得“成熟”了吧。2024年&#xff0c;学到了很多东西&#xff0c;做了很多项目&#xff0c;也帮别人解决了很多问题&#xff0c;唯独没有涨工资。来这…

Android系统开发(六):从Linux到Android:模块化开发,GKI内核的硬核科普

引言&#xff1a; 今天我们聊聊Android生态中最“硬核”的话题&#xff1a;通用内核镜像&#xff08;GKI&#xff09;与内核模块接口&#xff08;KMI&#xff09;。这是内核碎片化终结者的秘密武器&#xff0c;解决了内核和供应商模块之间无尽的兼容性问题。为什么重要&#x…

5G 核心网 相关概念快速入门

在我们开始阅读3GPP协议来学习5G核心网之前&#xff0c; 不妨来看看我之前整理的PPT&#xff0c;快速学习核心网相关概念&#xff0c; 以及5G转发面PFCP协议的相关核心知识。 涵盖了最精简的核心骨干内容&#xff0c;助你轻松上阵。 讲解目标 3GPP和相关协议 5G核心网架构模…

2025/1/20 学习Vue的第三天

玩性太大了玩得也不开心&#xff0c;天天看电视刷视频。 内心实在空洞。 最近天天看小红书上的外国人&#xff0c;结实外国友人&#xff08;狗头&#xff09;哈哈哈认识了不少人&#xff0c;有埃及的有美国的&#xff0c;还有天天看菲利普吃糖葫芦哈哈哈哈哈一个阳光的德国大男…

虚幻基础1:hello world

能帮到你的话&#xff0c;就给个赞吧 &#x1f618; 文章目录 hello world创建项目创建关卡创建蓝图将蓝图插入关卡中运行 hello world 本文引擎为5.5.1 创建项目 如图 创建后如图。 创建关卡 如图 创建蓝图 如图 选择actor 双击进入蓝图节点 选择事件图表 创…

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

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

SparkSQL数据源与数据存储综合实践

文章目录 1. 打开项目2. 查看数据集2.1 查看JSON格式数据2.2 查看CSV格式数据2.3 查看TXT格式数据 3. 添加单元测试依赖4. 创建数据加载与保存对象4.1 创建Spark会话对象4.2 创建加载JSON数据方法4.3 创建加载CSV数据方法4.4 创建加载Text数据方法4.5 创建加载JSON数据扩展方法…

鸿蒙Harmony json转对象(1)

案例1 运行代码如下 上图的运行结果如下: 附加1 Json_msg interface 案例2 import {JSON } from kit.ArkTS; export interface commonRes {status: numberreturnJSON: ESObject;time: string } export interface returnRes {uid: stringuserType: number; }Entry Component …

Maven私服-Nexus3安装与使用

写在前面 安装简单&#xff0c;此博客主要是为了记录下怎么使用&#xff0c;以及一些概念性的东西 安装配置 下载 下载对应版本&#xff08;科学上网&#xff09; https://help.sonatype.com/en/download-archives—repository-manager-3.html 设置端口 /etc/nexus-defaul…

MindAgent:基于大型语言模型的多智能体协作基础设施

2023-09-18 &#xff0c;加州大学洛杉矶分校&#xff08;UCLA&#xff09;、微软研究院、斯坦福大学等机构共同创建的新型基础设施&#xff0c;目的在评估大型语言模型在游戏互动中的规划和协调能力。MindAgent通过CuisineWorld这一新的游戏场景和相关基准&#xff0c;调度多智…