初识C++编程语言(万字详解)

目录

::域作用限定符

命名空间域(namespace):

流插入和流提取(C++的输入输出)

缺省参数:

函数重载: 

引用:

内联函数:

auto关键字:

1、类型思考:

2、auto介绍: 

auto的使用细则 :

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

2. 在同一行定义多个变量

3、auto不能使用的场景 

基于范围的for循环(C++11) 

1 、范围for的语法

 C++98中的指针空


::域作用限定符

在之前单纯的C语言中,同一个域里无法取得相同的名字这是很不方便的,在大型的工程中不同的程序员不可能做到所有变量都不相同,所以::域作用限定符应运而生。

例如:

 这种命名方式是不被允许的,在同一个域里,不能命名两个一样的变量。

#include<stdio.h>
int x = 0;
int main() {
	int x = 1;
	printf("%d\n", x);
	return 0;
}

所以我们可以向上面一样,将一个变量放在全局,一个放在局部。这样就不会报命名冲突的问题了,但是如果我们打印这个x变量,会发现屏幕上打印出来的是1。

为什么呢?🤔编译器会首先在局部域里找x,然后在去全局域里找,如果在局部域里找到了,自然就直接打印x了。

那么我们如果想要打印全局变量的这个0呢,我们可以这样:

#include<stdio.h>
int x = 0;
int main() {
	int x = 1;
	printf("%d\n", x);
	printf("%d\n", ::x);
	return 0;
}

 这时候就体现出了::的作用,如果::的左边什么都没有,那就是默认全局域,所以编译器会在全局域里找变量x。


命名空间域(namespace):

😎是为了解决命名空间里命名冲突的问题。

#include<stdio.h>

namespace project1 {
	int x = 1;
}
namespace project2 {
	int x = 2;
}

int main() {
	printf("%d\n", project1::x);
	printf("%d\n", project2::x);
	return 0;
}

我们如果想要命名同一个名字的话,我们就可以这样,用命名空间域来隔开,格式为:namespace+空间域名字。这样我们就可以用域空间操作符来指定使用变量名称了。

编译器搜索原则:

无指定:1、当前局部域  2、全局域  

有指定:1、直接在指定域中搜索

命令空间域里可以是:1、变量,2、函数,3、结构体。

#include<stdio.h>

namespace project1 {
	int x = 1;
}
namespace project2 {
    //变量
	int x = 2;
    //函数
	int Add(int a,int b){
		return a + b;
	}
    //结构体
	struct ListNode {
		/*....*/
	}LNode;
}

int main() {
	printf("%d\n", project1::x);
	printf("%d\n", project2::x);

	project2::Add(1,2);

	struct project2::ListNode phead;

	return 0;
}

需要注意的是:使用命名空间域里的结构体时,域名要在struct后结构体名前。

namespace还有一个使用方法:

当我们需要频繁调用project2时,就需要一直调用,就会变得很麻烦,所以我们介绍namespace的第二种用法:

这个叫做展开命名空间,也就是说使用了这个之后,project2就被展开了,被展开成了全局变量,再使用这个命名空间域里的东西的时候,就可以不用再引用了。

被展开的域相当于全局变量,所以当有局部变量的时候依然会优先访问局部变量。 

所以,当我们使用C++的时候,通常为了方便,会先写using namespace std,std就是C++的库,是为了方便调用C++库里面函数或者是关键字的。 (但是也仅仅是在我们平时的练习测试用的多,主要是为了方便)。

还有一种写法就是我可以展开这个库的一部分,也就是说:

就像这样,把几个常用的给展开,就可以了。

这时候有人要提出问题了,如果命名域的名字也冲突了怎么办?🤔

答:命名域允许嵌套,也就说如果命名域真的冲突了,我们也可以命明域进行嵌套来解决,而且如果我们想,我们可以无限的套娃下去。但一般我们嵌套两层就够用了。

可以看到这里我们在用的时候,就需要用两次::域作用限定符 。


流插入和流提取(C++的输入输出)

#include<iostream>
// std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中
using namespace std;
int main()
{
cout<<"Hello world!!!"<<endl;
return 0;
}

说明:
1. 使用cout标准输出对象(控制台)cin标准输入对象(键盘)时,必须包含< iostream >头文件
以及按命名空间使用方法使用std
2. cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,他们都包含在包含< 
iostream >头文件中。
3. <<是流插入运算符,>>是流提取运算符
4. 使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式。
C++的输入输出可以自动识别变量类型。

#include <iostream>
using namespace std;
int main()
{
   int a;
   double b;
   char c;
     
   // 可以自动识别变量的类型
   cin>>a;
   cin>>b>>c;
     
   cout<<a<<endl;
   cout<<b<<" "<<c<<endl;
   return 0;
}

// ps:关于cout和cin还有很多更复杂的用法,比如控制浮点数输出精度,控制整形输出进制格式等等。因为C++兼容C语言的用法,这些又用得不是很多,所以如果输出输入浮点数,我们还是采用C语言来实现 

std命名空间的使用惯例:
std是C++标准库的命名空间,如何展开std使用更合理呢?
1. 在日常练习中,建议直接using namespace std即可,这样就很方便。
2. using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对
象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模大,就很容易出现。所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 + 
using std::cout展开常用的库对象/类型等方式。


缺省参数:

#include<iostream>
using namespace std;

void Fun(int a = 10, int b = 20, int c = 30) {
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;

}
int main() {
	Fun(1,2,3);
	Fun(1,2);
	Fun(3);
	Fun();
	return 0;
}

 当我们来写一个函数的时候,如果我们传参了,那么就跟正常的一样,如果没传参,那么就会默认的用我们括号里面的值。

上面是缺省参数的四种形式,传参的时候如果我们想要修改其中的参数可以只传它的参数,没传参的就会默认括号里的值,但是不能进行跳跃传参,比如我们想只传b但是a,c还用默认值的话,这是办不到的。

还有一个是半缺省的形式, 像上面的b,我们可以不给默认值,但是这时候传参的话就必须传值了。

举一个实际的例子:

#include<iostream>
using namespace std;

struct Stack{
	int* a;
	int size;
	int capacity;
};
void StackInit(struct Stack* ps) {
	//ps->a = NULL;
	ps->a = (int*)malloc(sizeof(int) * 100);
}

int main() {
	struct Stack st1;
	StackInit(&st1);
	return 0;
}

我们假设初始化栈的时候,开辟栈的大小使用malloc,但是当我们有以下三种情况的时候:

这种情况下我们又怎么进行动态开辟呢,大小该给多少呢?

这时候我们的缺省参数就派上用场了:

#include<iostream>
using namespace std;

struct Stack{
	int* a;
	int size;
	int capacity;
};
void StackInit(struct Stack* ps ,int n = 4) {
	//ps->a = NULL;
	ps->a = (int*)malloc(sizeof(int) * n);
}

int main() {
	struct Stack st1;
	//确定要插入100个数据
	StackInit(&st1,100);

	struct Stack st2;
	//确定要插入10个数据
	StackInit(&st2,10);

	struct Stack st3;
	//不知道要插入多少的时候
	StackInit(&st3);

	return 0;
}

 这样是不是就很方便呢。

那当声明与定义分离的时候,该在哪里给缺省参数呢?

答案是:声明。                                                    
首先声明和定义肯定是不能同时给缺省参数的,因为当两个缺省参数不同时,就会报错。

其次,缺省参数是在调用的时候用的,那么将缺省参数放在声明才不会在编译的时候报错。

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


函数重载: 


C语言中我们不能命名相同名字的函数,在C++中我们可以命名相同函数的名字,但前提是:函数的参数的个数,类型,顺序不一样。

C语言做不到的,C++又是如何做到的呢?

C++明确了在调用的时候,不仅仅可以用函数的名字,还可以加上函数的参数类型合并起来在进行判断是否是重名的,并且还加上了参数数量的比较,就比如上面的两个Add,他们在编译完之后一个是Addci,另一个是Adddd。所以最后他们就是不同的函数。

但这里只是一个例子,不同的编译器会有不同的实现方式,但是思路都是一样的。


引用:

C语言中,我们如果想要指向一个变量的话,我们会将他的地址取出来存到指针变量里面,但是在针对一些复杂指针的时候,就很不方便,所以C++采用了引用。

#include<iostream>
using namespace std;
int main() {
	int a = 1;
	//引用
	int& b = a;
	cout << a << endl << b << endl;
	return 0;
 }

引用的形式就是:&(取地址符),如上面代码int& b = a,此时b就是a的别称,例如周树人的笔名是鲁迅,那么鲁迅和周树人都是指同一个人。所以引用的作用,就是给a取了一个别名b,那么无论输出a还是输出b,结果都是1。

#include<iostream>
using namespace std;
//这是我们C语言中的交换函数,必须传递实参的地址。
void Swap(int* x, int* y) {
	int tmp = *x;
	*x = *y;
	*y = tmp;
}
//这是用引用的写法,这里的x,y就是两个实参的别名
void Swap(int& x, int& y) {
	int tmp = x;
	x = y;
	y = tmp;
}
int main() {
	int a = 1;
	int c = 5;
	cout << a <<"<->" << c << endl;
	//Swap(a, c);
	Swap(&a, &c);
	cout << a << "<->" << c << endl;
	Swap(a, c);
	cout << a <<"<->" << c << endl;
	return 0;
 }

交换函数正常的实现,这就是引用的用法。

注意事项:

1、引用必须初始化,不可以写成:

int& b;
b = c;

 2、引用定义后不能改变指向,不能写成:

int& b = a;
int c = 3;
b = c; //这里就不是改变指向,而是赋值

3、 一个变量可以有多个引用,多个别名

int main() {
	int a = 1;
	int& b = a;
	int& d = a;
	int& e = a;
	return 0;
 }

这里面的bde都是a的别名。

既然引用的作用与指针作用重叠。

那么有小伙伴要提问了,那引用不是就替代指针了?🤔🤔🤔

 C++的引用是为了解决指针使用复杂场景的一些替换,让代码更简单易懂,但不能完全代替。

引用不能替代指针的原因:引用定义后不能改变指向。

例如:

 在双向链表中,删除中间的结点,该删除结点的前一个和后一个要改变指向,这是引用做不到的。

引用还有更为广泛的应用就是:

void PushBack(struct ListNode** phead,int x) {
	//........
}
void PushBack(struct ListNode*& phead, int x) {
	//........
}
int main() {
	struct ListNode* pList = NULL;
}

假如我们在PushBack函数里要对指针进行修改,那么我们就必须传一个二级指针(如第一个写法),那有了引用之后(第二个写法)ListNode*phead就是ListNode*pList的一个别名,所以当然可以在PushBack函数进行修改了。

还有一种经常出现在书上的写法让一些刚学C语言的小伙伴们十分头疼:

typedef struct ListNode {
	ListNode* prev;
	ListNode* next;
	int val;
}LNode, *PNode;

void PushBack(PNode& phead, int x) {
	//........
}
int main() {
	PNode pList = NULL;
	return 0;
}

这个*PNode就是struct ListNode的指针,所以指针类型就直接是PNode,然后再结合上&引用,就实现了这个的参数类型的写法。

然后我们来一个简易的顺序表感受一下C和C++的不同:

#include<iostream>
#include<assert.h>
using namespace std;

struct SeqList {
	int* a;
	int size;
	int capacity;
};
void SLInit(SeqList& sl) {
	sl.a = (int*)malloc(sizeof(int) * 4);
	sl.size = 0;
	sl.capacity = 4;
}
void SLModity(SeqList& sl, int pos,int x) {
	assert(pos >= 0);
	assert(pos < sl.size);
	sl.a[pos] = x;
}
void SLPushBack(SeqList& sl, int x) {
	sl.a[sl.size++] = x;
}
int SLGet(SeqList& sl, int pos) {
	assert(pos >= 0);
	assert(pos < sl.size);
	return sl.a[pos];
}
int main() {
	SeqList sl;
	SLInit(sl);
	SLPushBack(sl, 1);
	SLPushBack(sl, 2);
	SLPushBack(sl, 3);
	SLPushBack(sl, 4);
	for (int i = 0; i < sl.size; i++) {
		cout << SLGet(sl, i) <<" ";
	}
	cout << endl;
	for (int j = 0; j < sl.size; j++) {
		int val = SLGet(sl, j);
		if (val % 2 == 0) {
			SLModity(sl, j, val * 2);
		}
	}
	for (int i = 0; i < sl.size; i++) {
		cout << SLGet(sl,i) << " ";
	}
	return 0;
 }

这个代码嵌了一点点C++,但是跟C差不多。

#include<iostream>
#include<assert.h>
using namespace std;

struct SeqList {
	int* a;
	int size;
	int capacity;
	void Init() {
		a = (int*)malloc(sizeof(int) * 4);
		size = 0;
		capacity = 4;
	}
	void PushBack(int x) {
		a[size++] = x;
	}
	int& Get(int pos) {
		assert(pos >= 0);
		assert(pos <= size);
		return a[pos];
	}
};

int main() {
	SeqList sl;
	sl.Init();
	sl.PushBack(1);
	sl.PushBack(2);
	sl.PushBack(3);
	sl.PushBack(4);
	for (int i = 0; i < sl.size; i++) {
		cout << sl.Get(i) <<" ";
	}
	cout << endl;
	for (int j = 0; j < sl.size; j++) {
		if (sl.Get(j) % 2 == 0) {
			sl.Get(j)*= 2;
		}
	}
	for (int i = 0; i < sl.size; i++) {
		cout << sl.Get(i) << " ";
	}
	return 0;
 }

这里如果用int不加引用的话,相当于返回的是一个临时拷贝,临时变量是建立在堆上的,并且临时变量具有常性(可以理解为被const修饰过的),那么我们肯定是没办法修改的。就算这里不考虑常性,那修改的也只是这个临时变量,并没有修饰到顺序表中的本体,但是加了引用之后,不产生临时变量,引用就相当于返回了他的别名,那么修改别名就是修改了本体。所以用引用返回值具有有了读写功能。

引用和指针的区别:

语法层面:

1、引用是别名,不开空间,指针是地址需要开空间。

2、引用必须初始化,指针可以初始化也可以不初始化。

3、引用不能改变指向,指针可以。

4、引用相对更安全,没有空引用,但是空指针,容易出现野引用,但是不容易出现野指针。

5、sizeof、++、解引用访问等上面的区别。

底层: 

汇编层面上,没有引用只有指针,编译后引用也变成了指针。

在汇编层面上,引用和指针是没有区别的。 


内联函数:

C语言调用函数是需要开销的,假如说C语言有一个频繁调用的小函数:

int Add(int a, int b) {
	return a + b;
}

假如这个相加的小函数需要调用100w次,那就需要建立100w个栈帧空间。

那C语言是如何解决这个问题的:宏函数。

#define Add(a,b) ((a)+(b))

但是宏有很多缺点:

1、语法复杂,坑较多,不容易控制。

2、不能调试。

3、没有安全类型的检查。 

所以C++引出了内联函数:inline

inline int Add(int a, int b) {
	return a + b;
}

他的功能其实是和宏差不多,在多次调用的时候,不需要每次都建立栈帧。

并且优化了宏的缺点 。

inline函数的特性:

1、内联函数是一种时间换空间的做法,如果编译器把函数当作内联函数使用的时候,在编译过程中,编译器会把函数体替换为函数调用。缺点:函数体展开使目标文件变大。(当函数体较长,再去多次调用多次展开,会出现代码膨胀)优点:减少函数调用开销,提高代码运行效率。

2、将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰。

3、inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址
了,链接就会找不到。

// F.h
#include <iostream>
using namespace std;
inline void f(int i);
// F.cpp
#include "F.h"
void f(int i)
{
 cout << i << endl;
}
// main.cpp
#include "F.h"
int main()
{
 f(10);
 return 0;
}
// 链接错误:main.obj : error LNK2019: 无法解析的外部符号 "void __cdecl 
//f(int)" (?f@@YAXH@Z),该符号在函数 _main 中被引用

在C++中是比较排斥使用宏的,一般会采用以下方法来替代宏:

1、常量定义换用const、enum

2、短小函数定义换用inline


auto关键字:

1、类型思考:

随着我们学习的深入,变量的类型会越来越复杂,这就导致我们在使用的时候变得十分麻烦。

#include <string>
#include <map>
int main()
{
 std::map<std::string, std::string> m{ { "apple", "苹果" }, { "orange", "橙子" }, 
   {"pear","梨"} };
 std::map<std::string, std::string>::iterator it = m.begin();
 while (it != m.end())
 {
 //....
 }
 return 0;
}

std::map<std::string, std::string>::iterator 是一个类型,但是该类型太长了,特别容易写错。

2、auto介绍: 

auto 作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。言简意赅就是auto可以根据变量的值自动推导变量的类型。

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;
//auto e; 无法通过编译,使用auto定义变量时必须对其进行初始化
return 0;
}

【注意】
使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型 。

auto的使用细则 :

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

用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&

int main()
{
    int x = 10;
    auto a = &x;
    auto* b = &x;
    auto& c = x;
    cout << typeid(a).name() << endl;
    cout << typeid(b).name() << endl;
    cout << typeid(c).name() << endl;
    *a = 20;
    *b = 30;
     c = 40;
    return 0;
}

2. 在同一行定义多个变量

当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。 

void TestAuto()
{
    auto a = 1, b = 2; 
    auto c = 3, d = 4.0;  // 该行代码会编译失败,因为c和d的初始化表达式类型不同
}

3、auto不能使用的场景 

1. auto不能作为函数的参数

// 此处代码编译失败,auto不能作为形参类型,因为编译器无法对a的实际类型进行推导
void TestAuto(auto a)
{}

2. auto不能直接用来声明数组 

void TestAuto()
{
    int a[] = {1,2,3};
    auto b[] = {4,5,6};
}

基于范围的for循环(C++11) 

1 、范围for的语法

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

void TestFor()
{
int array[] = { 1, 2, 3, 4, 5 };
for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
     array[i] *= 2;
for (int* p = array; p < array + sizeof(array)/ sizeof(array[0]); ++p)
     cout << *p << endl;
}

对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。

void TestFor()
{
int array[] = { 1, 2, 3, 4, 5 };
for(auto& e : array)
     e *= 2;
for(auto e : array)
     cout << e << " ";
return 0;
}

 范围for相当于是依次取数组里面的值赋值给e,然后再将e输出,auto也是能更好的自动识别类型,以应对各种类型的数组,&是为了如果想要改变数组内容,那么我们引用就把e变成了数组每个元素的别名,就可以修改数组里面的值了。

注意:与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环。

void TestFor(int array[])
{
    for(auto& e : array)
        cout<< e <<endl;
}

 上面这个代码是不能用范围for的,现阶段范围for只能用于数组,但是在上面的TestFor函数中,array不是数组,而是一个指针。


 C++98中的指针空值

在良好的C/C++编程习惯中,声明一个变量时最好给该变量一个合适的初始值,否则可能会出现不可预料的错误,比如未初始化的指针。如果一个指针没有合法的指向,我们基本都是按照如下方式对其进行初始化:

void TestPtr()
{
int* p1 = NULL;
int* p2 = 0;
// ……
}

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

#ifndef NULL
#ifdef __cplusplus
#define NULL   0
#else
#define NULL   ((void *)0)
#endif
#endif

可以看到,NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量。不论采取何种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦,比如: 

void f(int)
{
 cout<<"f(int)"<<endl;
}
void f(int*)
{
 cout<<"f(int*)"<<endl;
}
int main()
{
 f(0);
 f(NULL);
 f((int*)NULL);
 return 0;
}

 程序本意是想通过f(NULL)调用指针版本的f(int*)函数,但是由于NULL被定义成0,因此与程序的初衷相悖。
在C++98中,字面常量0既可以是一个整形数字,也可以是无类型的指针(void*)常量,但是编译器默认情况下将其看成是一个整形常量,如果要将其按照指针方式来使用,必须对其进行强转(void *)0。

 所以从C++11以来用nullptr来填上了这个小坑。

#include<iostream>
using namespace std;
void f(int)
{
	cout << "f(int)" << endl;
}
void f(int*)
{
	cout << "f(int*)" << endl;
}
int main()
{
	f(0);
	f(NULL);
	f((int*)NULL);
	f(nullptr);
	int* p = nullptr;
	return 0;
}

注意:
1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。
2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。 


 

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

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

相关文章

HarmonyOS NEXT应用开发案例——列表编辑实现

介绍 本示例介绍用过使用ListItem组件属性swipeAction实现列表左滑编辑效果的功能。 该场景多用于待办事项管理、文件管理、备忘录的记录管理等。 效果图预览 使用说明&#xff1a; 点击添加按钮&#xff0c;选择需要添加的待办事项。长按待办事项&#xff0c;点击删除后&am…

java网络编程 01 IP,端口,域名,TCP/UDP, InetAddress

01.IP 要想让网络中的计算机能够互相通信&#xff0c;必须为计算机指定一个标识号&#xff0c;通过这个标识号来指定要接受数据的计算机和识别发送的计算机&#xff0c;而IP地址就是这个标识号&#xff0c;也就是设备的标识。 ip地址组成&#xff1a; ip地址分类&#xff1a;…

HCIP --- BGP 综合实验

实验拓扑图&#xff1a; 实验要求&#xff1a; 1.AS1存在两个环回&#xff0c;一个地址为192.168.1.0/24该地址不能 在任何协议中宣告 AS3中存在两个环回&#xff0c;一个地址为192.168.2.0/24该地址不能在任何协议中宣告&#xff0c;最终要求这两个环回可以互相通讯. 2.整个…

基于Netty框架的位置服务平台的设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 相关技术 3 1.1 开发环境及开发工具 3 1.2 相关知识简介 3 1.3 本章小结 4 2 系统分析 5 2.1 设计背景 5 2.2 系统需求分析 5 2.3 市场分析 5 2.4 论文的概要内容 6 2.5 本章小结 6 3 系统设计 7 3.1 系统总体设计 7 3.2 系统结构设计 8 …

【vue2基础教程】vue指令

文章目录 前言一、内容渲染指令1.1 v-text1.2 v-html1.3 v-show1.4 v-if1.5 v-else 与 v-else-if 二、事件绑定指令三、属性绑定指令总结 前言 Vue.js 是一款流行的 JavaScript 框架&#xff0c;广泛应用于构建交互性强、响应速度快的现代 Web 应用程序。Vue 指令是 Vue.js 中…

⎣优化技术⎤CoT-Decoding

微信公众号|人工智能技术派 作 者|hws 一种解码策略优化技术&#xff1a;目标是不需要任何显示的CoT prompting&#xff0c;能够有效提升大型语言模型在各种推理任务中的表现&#xff0c;并通过自发地揭示CoT推理路径&#xff0c;改善模型的推理能力和准确性。 背景介绍 大模…

打造你的HTML5打地鼠游戏:零基础入门教程

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

1-LINUX--系统介绍

1.目录结构 2.基本目录介绍 1.>/bin 存放常用命令&#xff08;即二进制可执行程序&#xff09; 2.>/etc 存放系统配置文件 3.>/home 所有普通用户的家目录 4.>/root 管理员用户的家目录 5.>/usr 存放系统应用程序及文档 6.>/dev 存放设备文件 7.>/lib 存…

阿里云99计划优惠:云服务器租用价格61元、99元、165元

阿里云99计划还有谁不知道么&#xff1f;阿里云不杀熟&#xff0c;新老用户同享&#xff0c;阿里云服务器99元一年&#xff0c;续费也是99元&#xff0c;续费不涨价家人们&#xff0c;2024年阿里云把云服务器价格打下来了&#xff0c;2核2G、2核4G、4核8G、4核16G、8核16G、8核…

Python匿名函数有知道的吗?

1.函数 按照函数是否有名字分为有名字的函数和匿名函数 匿名函数&#xff1a;定义函数时&#xff0c;不再使用def关键字声明函数&#xff0c;而是使用lambda表达式 匿名函数在需要执行简单的操作时非常有用&#xff0c;可以减少代码冗余 2.有名字的函数 def fn(n):return …

【漏洞复现】TeamCity身份验证绕过漏洞CVE-2024-27198

漏洞描述 JetBrains TeamCity是一款由JetBrains开发的持续集成和持续交付(CI/CD)服务器。它提供了一个功能强大的平台,用于自动化构建、测试和部署软件项目。TeamCity旨在简化团队协作和软件交付流程,提高开发团队的效率和产品质量。 JetBrains TeamCity在2023.11.4版本之前…

CSS的盒子模型:掌握网页设计的基石!

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

EndNote插入引文换行不顶格的解决方法

引文换行不顶格 下载下的endNote的文献换行不顶格&#xff0c;如链接中EndNote插入引文换行不顶格的解决方法所示&#xff0c;换行不顶格。 解决方法 打开EndNote&#xff0c;依次打开「Edit」→「Output Styles」→「Edit"“」→「Bibliography」→「Layout」。 以编辑…

《汇编语言》- 读书笔记 - 第17章-实验17 编写包含多个功能子程序的中断例程

《汇编语言》- 读书笔记 - 第17章-实验17 编写包含多个功能子程序的中断例程 逻辑扇区根据逻辑扇区号算出物理编号中断例程&#xff1a;通过逻辑扇区号对软盘进行读写 代码安装 int 7ch 测试程序效果 实现通过逻辑扇区号对软盘进行读写 逻辑扇区 计算公式: 逻辑扇区号 (面号*8…

海外媒体发稿:7种媒体套餐推广策略解析-华煤舍

有效的媒体宣传策略对于产品或服务的推广至关重要。本文将介绍7种媒体套餐推广策略&#xff0c;帮助您惊艳市场&#xff0c;并取得成功。以下是每种策略的拆解描述&#xff1a; 1. 广告投放 广告投放是最常见的宣传手段之一。通过在各种媒体平台上购买广告&#xff0c;如电视、…

深度学习:如何面对隐私和安全方面的挑战

深度学习技术的广泛应用推动了人工智能的快速发展&#xff0c;但同时也引发了关于隐私和安全的深层次担忧。如何在保护用户隐私的同时实现高效的模型训练和推理&#xff0c;是深度学习领域亟待解决的问题。差分隐私、联邦学习等技术的出现&#xff0c;为这一挑战提供了可能的解…

基于机器学习的网络入侵检测与特征选择及随机森林分类器性能评估(NSL-KDD数据集)

简介 本文将详细介绍如何利用Python和相关机器学习库对NSL-KDD数据集进行预处理&#xff0c;特征选择&#xff0c;并通过随机森林算法构建网络入侵检测模型。同时&#xff0c;还将展示如何计算并可视化模型的ROC曲线以评估其性能。 首先&#xff0c;我们导入了必要的库&#…

问答系统设计:核心架构解析

在近几年中,问答回答(QA)应用的快速发展彻底改变了我们获取信息的方式。无论是在搜索引擎、聊天机器人,还是在从大量主题数据中检索相关信息的应用程序中,QA应用的身影无处不在。 简而言之,QA应用的主要目的是在文本段落中找到对特定问题最合适的答案。早期的一些方法包…

【考研数学】129高分学姐二战经验+资料分享

21年数学三87分 22年数学三129分 可以说这两年该踩的雷我都踩了、该做的题我都做了。 进来看看是什么使我突然醒悟让我数学提分40多分的叭。 李林的880题我也做过&#xff0c;先来说说这本书的优缺点以及适用人群吧。 习题优点 李林老师的880题难度适中&#xff0c;很贴近…

Day01-项目介绍及初始化-登录页面(test)

1.人力资源项目介绍 1.1 项目架构和解决方案 1.2 课程安排 1.3 课程具备能力 1.4 课程地址 vue-element-admin文档地址&#xff1a;链接演示地址&#xff1a; 链接人力资源项目演示地址&#xff1a; 链接 2. 拉取项目基础代码 拉取命令 $ git clone https://github.com/P…