C++入门全集(1):初窥门径

一、前言

C++是一种计算机高级程序设计语言,它在C语言的基础上进行了进一步的扩充和完善,并增加了许多有用的库,是一种面向对象的程序设计语言。

所以,C++是兼容C语言语法的。

我打算把所有C++入门需要学习的知识整合成一个全集,方便各位,也能方便自己复习。

本文主要讲解C++相对C语言的查漏补缺和优化部分,也为后续学习类和对象打基础。

二、C++关键字

C语言有32个关键字,而C++有63个关键字,不过这些关键字无法一次学完,我们这里先混个脸熟

asmdoifreturntrycontinue
autodoubleinlineshorttypedeffor
booldynamic_castintsignedtypeidpublic
breakelselongsizeoftypenamethrow
caseenummutablestaticunionwchar_t
catchexplicitnamespacestatic_castunsigneddefault
charexportnewstructusingfriend
classexternoperatorswitchvirtualregister
constfalseprivatetemplatevoidtrue
const_castfloatprotectedthisvolatilewhile
deletegotoreinterpret_cast

三、命名空间

在C语言中,命名冲突问题时常存在,例如我们无法定义一个名为rand的变量,因为在stdlib.h中已经有函数取名为rand了

如果我们将所有的变量名、函数名和类名都存放在全局作用域中,就可能导致命名冲突,所以C++中出现了命名空间这一概念。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染。

3.1 命名空间的定义

要定义一个命名空间,需要使用到关键字namespace,然后给命名空间取个名,再用大括号括起来,大括号中即为命名空间的成员

namespace test
{int rand = 10;
}

除了变量,命名空间中还可以定义函数或者结构体类型

另外,命名空间还可以嵌套,如:

namespace test1
{namespace test2{int rand = 10;}
}

如果命名空间也同名了怎么办呢?同一个工程的不同文件中可能出现多个同名的命名空间,此时编译器会将它们合并为同一个命名空间。

3.2 命名空间的使用

当我们学会在命名空间中定义变量、函数和类型后,该如何使用它们呢?

(1)使用作用域限定符

所谓作用域限定符就是两个冒号 "::"

像这样,就可以访问到两个不同命名空间的变量a了

(2)使用using引入命名空间成员

变量b是命名空间test1的成员,我们可以通过using引入它,所以下面main函数中我们访问变量b就不需要使用作用域限定符了

(3)使用using namespace

像这样,我们使用using namespace引入命名空间test1,所以没有使用作用域限定符的a就访问到了test1中的a,而下面使用了作用域限定符就会访问test2中的a

在后面学习C++的输入和输出中,我们会学到cout和cin,二者的定义是放在名为std的一个C++标准库的命名空间中的,C++将标准库的定义实现都放在这个命名空间中。

如果不使用using namespace,每次使用的时候就要用到作用域限定符,也就是变成std::cout和std::cin,十分的麻烦。

所以我们在使用它们的时候一般会先输入“using namespace std;”,避免每次要输入和输出的时候都使用作用域限定符。

四、C++的输入和输出

听说每一个程序员的第一个程序都是hello world,我们来使用C++实现一下

#include <iostream>using namespace std;int main()
{cout << "Hello world" << endl;return 0;
}

从这一段简短的代码中,我们可以总结如下信息:

  • cout和cin是全局的流对象,endl是特殊的C++符号,表示换行,它们都包含在<iostream>头文件中
  • <<是流插入运算符,>>是流提取运算符

实际上,cout和cin分别是ostream和istream类型的对象,而<<和>>在C语言中原本是位运算符,在C++却变了,这里也涉及到运算符重载的知识,在后续我们还会对其进行深入的学习

注意:早期的标准库将所有功能都在全局域中实现,并声明在以.h为后缀的头文件中,使用时也只需要包含对应头文件即可。而后来则将其实现在std命名空间下,为了和头文件区分,规定C++的头文件不带.h。一些旧编译器可能还支持<iostream.h>的格式,不过还是推荐使用<iostream>+std的方式

使用cout和cin的好处在于更方便,不需要像printf和scanf一样手动控制格式

缺点在于打印一串数据的情况会比较繁杂

所以我们根据实际情况选择更优的方式

在日常练习中,我们当然可以使用using namespace std,怎么方便怎么来。

但是这样做,整个标准库就全部暴露出来了,此时如果我们定义了和库中重名的类型/对象/函数,就会出现冲突问题。所以在项目开发中不推荐使用全局展开,我们可以指定命名空间访问,例如using std::cout和using std::cin来展开常用的命名空间成员

五、缺省参数

缺省参数就是我们声明或定义函数时可以为函数的参数指定一个值,在调用函数的时候没有指定的实参,就使用这个预先设定的默认值

缺省参数又分为全缺省参数和半缺省参数

关于缺省参数,我们需要注意几点:

(1)半缺省参数必须从右到左依次给出,不能间隔着给

(2)缺省参数不能同时出现在函数的定义和声明中

像这样,函数的定义和声明中同时出现缺省参数,而两个位置设置的值不同,编译器就无法确定该使用哪个缺省值

(3)缺省值必须是常量或者是全局变量

六、函数重载

C++允许在同一作用域中声明几个功能类似的同名函数,前提是这些同名函数的形参个数/类型/类型顺序不同。

例如我们以前在C语言中想实现Add函数,但是int和double类型的数据不能用同一个函数处理,每处理一种类型的数据就要写一个函数,函数间还不能同名

但是在C++中针对这个问题进行了优化,编译器会有一套自己的函数名修饰规则来修饰不同形参个数/类型/类型顺序的同名函数

#include <iostream>
using namespace std;//参数类型不同
int Add(int x, int y)
{return x + y;
}double Add(double x, double y)
{return x + y;
}//参数个数不同
void f(int a)
{cout << "void f(int a)" << endl;
}void f(int a, int b)
{cout << "void f(int a,int b)" << endl;
}//参数类型的顺序不同
void f(int a, char b)
{cout << "void f(int a, char b)" << endl;
}void f(char a, int b)
{cout << "void f(char a, int b)" << endl;
}int main()
{Add(1, 2);Add(1.1, 2.2);f(1);f(1, 2);f(10, 'a');f('a', 10);return 0;
}

C++支持函数重载的原理就是——名字修饰(name Mangling)

名字修饰是一种在编译过程中,将函数、变量的名称重新改编的机制。简单来说就是编译器为了区分多个同名函数,规定了一个新的规则来对原本的名字进行修饰

为什么C语言不支持函数重载,是因为它的名字修饰规则过于简单,只是在函数名前面添加了下划线

拓展:在C++的函数前加上extern "C" 就可以让函数按照C语言的风格编译

这里可以看到,Add函数按照C语言的风格编译后名字变为了_Add

而在C++中,修饰规则得到了完善,所以可以支持函数重载

不过不同的编译器有自己的函数名修饰规则,上面的就是在Windows下vs的修饰规则,有点过于复杂了,有兴趣的同学可以自行深入学习。

接下来我们展示g++的修饰规则,它会比前者更加的简单易懂

#include <iostream>
using namespace std;int Add(int x, int y)
{return x + y;
}double Add(double x,double y)
{return x + y;
}int main()
{Add(1, 2);Add(1.1, 2.2);return 0;
}

上面的是源文件代码,我们在终端中输入"g++ -S test.cpp -o test.s"来查看其汇编代码

可以看到,这两个就是上面int类型的Add函数和double类型的Add函数重载后的名字了。

其中_Z后跟着的数字就是原函数名的长度,后面的 "ii" 和 "dd" 就是参数的类型。

通过这些,我们就能理解为什么C语言不支持函数重载,而C++通过函数名的修饰规则可以区分同名函数了,只要参数个数/类型/类型顺序不同,修饰后的名字就不同,也就可以区分了。

需要注意的是,如果两个函数的函数名和参数个数/类型/类型顺序都相同,也是无法区分的。

七、引用

引用就是给已经存在的变量取一个别名,编译器不会为引用变量开辟内存空间,而是和它引用的对象共用同一块内存空间,引用的符号和取地址符号&一样。

需要注意的是,引用变量必须和被引用的对象是同一类型的

引用变量也可以作为被引用的对象

引用还可以代替指针的传址调用,例如以前我们要实现Swap函数,需要指针传地址才能成功交换,现在可以换成引用,此时形参是实参的别名。

当然,指针也可以进行引用

7.1 引用的特性

(1)引用在定义时必须初始化

(2)一个变量可以有多个引用,也就是取多个别名

(3)一旦引用变量已经引用过了某个对象,就再不能引用其他对象

可以看出,引用和指针还是有区别的,像在链表这些地方我们还是选择使用指针,而在一些输出型参数,也就是形参的改变要影响实参的地方我们可以选择使用引用

7.2 常引用

(1)如果被引用的对象被const修饰,而引用变量没有被const修饰会报错

(2)引用变量如果没有被const修饰,不能将常量作为引用对象

(3)引用变量没有被const修饰且和被引用对象不是同一类型时会报错

7.3 引用的使用场景

(1)引用作为函数参数,就是上面提到过的Swap

(2)引用作为函数返回值

int& Add(int a, int b)
{int c = a + b;return c;
}int main()
{int& ret = Add(1, 2);Add(3, 4);cout << "Add(1, 2) is :" << ret << endl;cout << "Add(1, 2) is :" << ret << endl;return 0;
}

上面的代码会输出什么结果?

实际上,结果是未定义的。

第一次调用Add函数的时候,函数栈帧创建完毕,局部变量c(此时值为3)保存在Add的栈帧中。函数运行结束后,栈帧销毁,内存空间被系统回收,此时变量c已经没有意义了,所以ret引用了一块已经被释放的空间。

第二次调用Add函数和第一次一样,只不过局部变量c的值变为了7。

需要注意的是,虽然空间被回收,里面的东西却都还在。就像去住酒店,退房后里面的东西在没打扫前都是一直保持原样的,而不是说退房后里面的东西就都没了。

所以,当我们第一次输出ret的值是7,第二次就变为了随机值

因此,如果出了函数作用域后返回对象没有销毁(static,malloc等),则可以使用引用返回,否则必须使用传值返回

另外的,引用返回还可以修改返回的对象

#include <iostream>using namespace std;int& Func(int* a, int i)
{return a[i];
}int main()
{int a[10] = { 1,2,3,4,5,6,7,8,9,10 };for(int i = 0 ;i<10;i++){Func(a, i) = i * 10;cout << a[i] << " ";}return 0;
}

7.4 传值和引用返回的效率比较

以值作为函数参数或返回值类型的时候,函数并不会直接传递实参或者将变量本身直接返回,而是会创建一个临时变量作为“中间商”,因此会影响效率,我们以传值返回为例测试一下

#include <iostream>
#include <time.h>
using namespace std;struct A 
{ int a[10000];
};A a;// 值返回
A TestFunc1()
{return a;
}
// 引用返回
A& TestFunc2()
{ return a;
}int main()
{// 以值作为函数的返回值类型size_t begin1 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc1();size_t end1 = clock();// 以引用作为函数的返回值类型size_t begin2 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc2();size_t end2 = clock();// 计算两个函数运算完成之后的时间cout << "TestFunc1 time:" << end1 - begin1 << endl;cout << "TestFunc2 time:" << end2 - begin2 << endl;return 0;
}

可以看到,传值返回比引用返回效率低了许多

7.5 引用和指针的区别

从底层来看,引用还是按照指针的方式来实现的,我们可以观察一下汇编代码

二者的不同点在于:

  • 从概念上来说,引用是定义了一个变量的别名,指针是存储了变量的地址
  • 引用在定义时必须初始化,指针可以不用
  • 引用在初始化时引用了一个对象后,就不能再引用其他对象,而指针可以随时改变指向
  • 没有空引用,但是有空指针
  • 从sizeof来说:引用的sizeof结果是引用类型的大小,但指针始终是地址所占字节个数
  • 引用的++是被引用的对象+1,而指针++是指针向后偏移一个类型的大小
  • 多级指针之间的含义不同,但多级引用指向的是同一块空间
  • 访问对象的方式不同,指针需要解引用,而引用是由编译器自己处理
  • 引用比指针使用起来更安全

八、内联函数

在C++中,为了解决一些频繁调用的小函数大量消耗栈内存的问题,引入了inline修饰符

以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开函数,不用调用函数建立栈帧。 

其作用很像宏函数,不过相比宏函数的缺点,它可以调试,有类型的检查,不容易出错。

inline int Add(int x, int y)
{return x + y;
}

inline是一种比宏更简单更好的方式,并且不降低效率。

如果不用inline修饰,在汇编代码中我们会看到用call指令去调用函数的操作

但是在Add函数前增加inline将其修改为内联函数,在编译期间编译器会用函数体替换函数的调用。

我们可以在release模式下查看汇编代码中是否存在call Add的指令

如果想在debug模式下查看,需要进行一些设置,因为在debug模式中默认情况下编译器不会对代码进行优化

在项目中点击属性

在属性中修改这两项

​​​​​​​

然后我们在debug模式下查看内联函数的汇编代码

可以看到,已经没有call指令了。

inline是一种以空间换时间的做法,这里的空间指编译出来的可执行文件的大小,内联函数会直接在程序中展开,越长的函数调用越多次就会使文件大小暴增。

inline只是向编译器发出的一个请求,编译器可以选择忽略该请求

假如有一个1000行的函数,我们要在程序中调用1000次,如果不用inline修饰的话就是1000+1000行代码,如果用inline修饰的话就是1000*1000行代码,换做是你你觉得哪个更好?

可以看到,太长的函数尽管用了inline修饰,编译器也会忽略掉,选择call调用函数

一般建议将函数规模较小、非递归且调用次数较多的函数使用inline修饰

需要注意的是,inline不建议声明和定义分离,会导致链接错误,对于内联函数最好直接在头文件中定义

此时在test.cpp中,编译时展开了Func.h的内容,而里面只有Func函数的声明,只能等链接的时候在符号表中寻找对应函数,也就是通过call指令调用函数,而内联函数是不会生成call指令的

所以我们直接在头文件中定义内联函数即可

九、auto关键字(C++11)

随着我们不断深入学习C++,程序越来越复杂,使用的类型也会越来越复杂,不仅难于拼写,还容易出错。

除了typedef,我们还有另一个选择就是auto,它可以帮助我们自动推导类型

需要注意的是,使用auto定义变量时必须对变量进行初始化,因为在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。

因此,auto并非是一种类型的声明,而是一个占位符,编译器在编译时会将auto替换为变量实际的类型 

9.1 使用auto的注意事项

(1)如果auto后加上*就限定了赋值的对象必须是指针

(2)我们使用auto时,也可以在同一行定义多个变量,前提是这些变量必须是相同的类型

(3)用auto声明引用类型时还是要加上&的

#include <iostream>
using namespace std;int main()
{int a = 10;auto& b = a;return 0;
}

9.2 不能使用auto的场景

(1)auto不能在函数的参数中使用

(2)auto不能用于声明数组

十、范围for(C++11)

现代C++倾向于让各种繁杂的操作变得简洁,因此诞生了许多语法糖,范围for算是其中的典型。

在C++98/03中,不同的容器和数组遍历的方式有很多,不够统一,也不够简洁。

而C++11出现了基于范围的for循环,可以更简洁的去遍历容器和数组,也更方便我们使用了。

以前我们遍历数组的方式如下:

int main()
{int array[] = { 1,2,3,4,5 };for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++){cout << array[i] << " ";}cout << endl;return 0;
}

对于一个有范围的集合而言,由程序员来声明循环的范围未免太多余,还容易出错。接下来我们来使用范围for遍历数组:

for循环的括号中由冒号":"分为两部分,左边是范围内用于迭代的变量,右边表示被迭代的范围

这里也用到了前面的auto关键字,如果我们想对范围内的元素进行修改,还可以用到引用&

和普通循环一样,范围for中也可以使用continue和break。

需要注意的是,范围for迭代的范围必须是确定的。对于数组而言,就是数组第一个元素到最后一个元素的范围;对于类而言,应该提供begin和end的方法,begin和end就是for循环迭代的范围。

void Func(int array[])
{for (auto x : array)cout << x << endl;
}

像这种情况就不能使用范围for,因为传参到函数中时传递的不是一整个数组而是数组指针,此时for的范围不确定。

十一、指针空值nullptr(C++11)

在过去,我们给一个没有指向的指针进行初始化的时候会使用NULL,而NULL实际上是一个宏。

我们在C语言中使用NULL没有问题,但是在C++中就会出现问题,为什么呢?

在传统的C头文件stddef.h中,可以看到如下代码:

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

可以看到,在C++中NULL被定义为0,这样会造成什么麻烦呢?

可以看到,就算传递的参数为NULL,程序还是会调用int类型的Func,而不是int*的Func,这违背了我们的目的。

因此出现了指针空值nullptr来填补这个bug,使用nullptr时不需要包含头文件,因为它是C++11作为新关键字引入的。为了提高代码的健壮性,我们后续表示指针空值时最好都使用nullptr。

有人会想,为什么不直接把这个bug修改了呢?因为语言有一个向前兼容的原则,也就是已经出现的东西即使有问题也不能修改,如果贸然去修改了可能会导致以前的代码无法运行,可能会造成巨大的损失。

到这里,我们就算对C++有了一个简单的了解了,下一篇的C++入门我们就会开始学习类和对象。

如果觉得本文对你有帮助就点个赞吧

完.

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

在c++中最重要的语法:类。第一章,什么是类,如何认识类,怎么使用类?

这一篇&#xff0c;简单介绍类的基本认知&#xff0c;和细节。 在c中&#xff0c;我们很多时间都要和类去打交道。它也是c相较于c新增的一个比较好用的语法。 类的定义如下&#xff1a; class A{private:成员函数或者成员属性public:成员函数或者成员属性protected:成员函数…

【C++】友元、初始化列表、内部类、static修饰成员详解

文章目录 前言1. 构造函数不为人知的那些事1.1 构造函数体赋值1.2 初始化列表1.3 explicit关键字 2. static成员2.1 概念2.2 特性2.3 小总结 3. C11 成员变量初始化新用法4. 友元4.1 友元函数4.2 友元类 5. 内部类5.1概念及特性 总结 前言 提示&#xff1a;这里可以添加本文要…

IntelliJ IDEA 2023.3发布,AI 助手出世,新特性杀麻了!!

目录 关键亮点 对 Java 21 功能的完全支持 调试器中的 Run to Cursor&#xff08;运行到光标)嵌入选项 带有编辑操作的浮动工具栏 用户体验优化 Default&#xff08;默认&#xff09;工具窗口布局选项 默认颜色编码编辑器标签页 适用于 macOS 的新产品图标 Speed Sear…

【JavaScript 漫游】【011】ES5 规范中 Array 对象方法汇总

文章简介 本文为【JavaScript 漫游】专栏的第 011 篇文章&#xff0c;记录的内容包含了 ES5 规范中Array 对象的所有方法。 Array()Array.isArray()valueOf()、toString()push()、pop()shift()、unshift()join()concat()reverse()slice()splice()sort()map()forEach()filter(…

携程网首页案例制作(移动端)

技术选型 方案&#xff1a;采用单独制作移动页面方案 技术&#xff1a;布局采用flex布局 body样式 通常要设置最大宽度&#xff0c;最小宽度&#xff0c;水平居中&#xff0c;字体设置&#xff0c;背景颜色以及相关初始化 body {max-width: 540px;min-width: 320px;margin…

Spring Boot 笔记 002 整合mybatis做数据库读取

概念 MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO&#xff08;Plain Old Java Objec…

MySQL之体系结构

华子目录 MySQL简介MySQL的特性MySQL版本MySQL常见版本 数据库排名网站MySQL结构体系查看最大连接数查询缓存配置情况 一条SQL语句执行流程 MySQL简介 MySQL是一个小型关系数据库管理系统&#xff0c;开发者为瑞典MySQL AB公司。在2008年1月16号被sun公司10亿美金收购。2009年…

RNN(神经网络)

目录 介绍&#xff1a; 数据&#xff1a; 模型&#xff1a; 预测&#xff1a; 介绍&#xff1a; RNN&#xff0c;全称为循环神经网络&#xff08;Recurrent Neural Network&#xff09;&#xff0c;是一种深度学习模型&#xff0c;它主要用于处理和分析序列数据。与传统…

STM32启动过程浅析

MAP文件浅析 MDK编译过程文件&#xff08;11种&#xff09; .o&#xff1a;可重定向对象文件&#xff0c;每个.c、.s文件编译后都生成一个.o文件.axf&#xff1a;可执行对象文件&#xff0c;由.o文件链接生成&#xff0c;仿真的时候需要用到此文件.hex&#xff1a;INTEL Hex格…

[算法前沿]--058- LangChain 构建 LLM 应用详细教程

什么是LLMs? LLM,即大型语言模型,是指经过大量文本数据训练的最先进的语言模型。它利用深度学习技术来理解和生成类似人类的文本,使其成为各种应用程序的强大工具,例如文本完成、语言翻译、情感分析等。LLMs最著名的例子之一是 OpenAI 的 GPT-3,它因其语言生成能力而受到…

HTTP2: springboot启用http2

springboot http2应用条件 使用servlet 4.0jdk 9tomcat 9 springboot 开启h2 创建证书 创建脚本&#xff1a; keytool -genkey -keyalg RSA -alias wisely -keystore keystore.jks -storepass pass1234 -validity 4000 -keysize 2048添加springboot配置 server:port: 808…

Sentinel 源码分析

Sentinel源码分析 项目源码 1.Sentinel的基本概念 Sentinel实现限流、隔离、降级、熔断等功能&#xff0c;本质要做的就是两件事情&#xff1a; 统计数据&#xff1a;统计某个资源的访问数据&#xff08;QPS、RT等信息&#xff09;规则判断&#xff1a;判断限流规则、隔离规…

NGINX upstream、stream、四/七层负载均衡以及案例示例

文章目录 前言1. 四/七层负载均衡1.1 开放式系统互联模型 —— OSI1.2 四/七层负载均衡 2. Nginx七层负载均衡2.1 upstream指令2.2 server指令和负载均衡状态与策略2.2.1 负载均衡状态2.2.2 负载均衡策略 2.3 案例 3. Nginx四层负载均衡的指令3.1 stream3.2 upstream指令3.3 四…

油猴脚本开发总结

一、在线安装 打开浏览器&#xff0c;点击右上角“ ”&#xff0c;在弹出的菜单上点击“拓展”跳转到下面这个页面&#xff1a; 点击"获取Microsoft Edge拓展"&#xff1a; 然后搜索框输入“tampermonkey”&#xff1a; 获取最上面这个黑绿色拓展&#xff1a; 二、…

vulnhub中Beelzebub靶机

渗透思路 一.信息收集1.网段探测2.端口探测3.常见漏洞扫描4.目录扫描5.web页面分析 二.渗透继续目录扫描ssh连接提权提权&#xff0c;flag 一.信息收集 1.网段探测 ┌──(root㉿kali)-[~] └─# nmap -Pn 192.168.0.0/24 --min-rate 10000 Starting …

java实现栈功能

1.使用数组方式 public static void main(String[] args) throws Exception {BufferedReader br new BufferedReader(new InputStreamReader(System.in));int operateNum Integer.parseInt(br.readLine());//操作次数String inputInfo;//输入信息StringBuilder outputSb new…

吉他学习:右手拨弦方法,右手拨弦训练 左手按弦方法

第六课 右手拨弦方法https://m.lizhiweike.com/lecture2/29362775 第七课 右手拨弦训练https://m.lizhiweike.com/lecture2/29362708

SDL库的下载与配置(Visual Studio )2024/2/4更新

一.SDL的下载 下载链接 二.SDL的环境配置 解压以后放在中文路径下 不会添加环境变量自行搜索&#xff08;比较简单网上教程很多&#xff09; 下面进行编译器的配置 复制这段内容 x64\SDL2main.lib x64\SDL2.lib将这段代码放进去运行一下 #include <SDL.h>int main(int…

07-使用Package、Crates、Modules管理项目

上一篇&#xff1a;06-枚举和模式匹配 当你编写大型程序时&#xff0c;组织代码将变得越来越重要。通过对相关功能进行分组并将具有不同功能的代码分开&#xff0c;您可以明确在哪里可以找到实现特定功能的代码&#xff0c;以及在哪里可以改变功能的工作方式。 到目前为止&…

量子计算+材料建模的理论效率提升100000倍!英国公司Phasecraft取得算法突破

编辑丨慕一 编译/排版丨沛贤 深度好文&#xff1a;1250字丨6分钟阅读 在量子计算近期可能的商业应用中&#xff0c;材料建模最有前景的领域之一。在这个领域的应用可能只需要几千个量子比特&#xff0c;而不像其他应用需要数百万个量子比特。目前该领域是量子计算的研究热点…