写日志的目的有两个:一是记录自己的成长;二是方便以后回忆忘却的知识。

2024.7.13

已经高考完一个多月了,本来打算用暑假学一下c++。
暑假已经过去差不多一半了,可以说我这个高考后的暑假目前几乎毫无意义,并没有感觉比平时快乐多少,也几乎没学到什么东西,没得到什么东西(除了自己买的耳机)。

感觉其他人的暑假都很有意义,每次我玩游戏的时候都有一些负罪感,感觉也没有以前快乐了,也可能是没人陪我的缘故。

所以我重拾以前的目标,打算学一门编程语言,最终权衡之后决定选择c++。虽然它在我想做的mc模组或整合包或者服务端插件方面几乎没用,但是它是一门很接近计算机底层的语言。

之前的一个月也零散地学习过一点,但由于内容比较少,我决定将它们合并写到一天的日志里。

环境我选择manjaro系统,ide选择vscode。
虽然用linux开始时比较麻烦,但在我看来它比较有仪式感,而且相对windows,它可以让我更加专注。
用了一段时间后发现其实linux也很好使。

我选择跟随下面的视频学习:https://www.bilibili.com/video/BV1Dk4y1j7oj

vscode小细节

首先是vscode的一些注意事项:
要比较方便地调试和编译记得更改.vscode/launch.json的program那一行。
"program": "${fileDirname}/${fileBasenameNoExtension}",
tasks.json我记得好像可以自动生成。

预处理语句相关

#include等带#的都是预处理语句,它们在编译开始之前就被处理了。

比如#include <iostream>是指包含了<iostream>头文件。
这里如果是系统头文件就用<>
自定义的头文件用""
头文件的后缀名一般是.h,c++自带的头文件一般没有后缀名。

#include的本质是将头文件的内容复制到自己的位置,值得注意的是预处理语句后面好像都不用带;

头文件中的#pragma once的作用是防止重复的内容引起错误。

using namespace std;目前还未深入了解。

变量相关

变量的本质是存储在内存中的数据,
不同变量类型的根本区别是所用内存空间不同,比如bool变量占一个字节,而int占4个。
常用的变量还有:char(1字节)short(2字节)long(通常为4字节,取决于编译器)long long(通常8字节)。
一些不太常用的灵活组合:long int(8字节)。
可以在变量类型前加unsigned用来去除符号位,可以让变量存储更大的数字。例如unsigned int
char可以存储字符,而不只是数字。比如char a = 'A'char a = 65在输出变量a时结果都为A。但如果是short类型:short b = 'A'则输出结果为65
值得注意的是bool,其值为0时代表false,其余都代表true。但是其设置为比如6和7的效果在不同情况下也不同,下面的if条件句会提到。
void代表无意义的类型。

更多变量类型:https://www.runoob.com/cplusplus/cpp-variable-types.html

函数

函数可以看做一个可以被调用的代码块,有输入值,可以返回输出值。
按照以下格式创建一个函数:

返回值类型 函数名称(参数1的类型 参数1的名称,参数2的类型 参数2的名称, ...){函数体}

比如

int Plus(int a1, int a2) 
{
    return a1 + a2;
}

调用函数示例:int y = Plus(50 ,100);

一个小发现:不能在函数内定义函数。
函数一般都要有返回值,即带return关键字,但main函数例外,或可以在main函数最后写return 0
调用一个在另一文件中的函数需要提前声明,声明函数即定义函数去掉函数体的部分比如int Plus(int a1, int a2)
需要多次声明或声明多个函数时,可以用到头文件

2024.7.14

if语句

在正式提到if之前,先来说一下===的区别:
=用来给变量赋值,==则用来比较变量是否等于某个值。
比如

bool bo = x == 5

如果x的值为5,则botrue,反之则为false

if语句示例:

if(条件)
       条件满足时执行的代码

比如

if(x == 3)
        cout << "Hello World!" << endl;

如果条件是一个bool变量时则可以简化为:

if(bo)
        cout << "Hello World!" << endl;

代表botrue时执行输出Hello World!

小细节:

bool bo = 6
if(bo == 7)
        cout << "Hello World!" << endl;
//即便bo是一个bool变量,6和7都代表true,但并不会输出Hello World!

加入else if和else的时候执行优先级从上到下,只有前面的条件都不满足,才会执行后面的,比如:

int main() {
    int x = 5;
    bool bo = 7;
    if(x == 3)
        cout << "Hello World!" << endl;
    else if (x > 10)
        cout << "Hello Again!" << endl;
    else if (bo)
        cout << "Hello World!11111+" << endl;
    else 
        cout << "Goodbye World!" << endl;
}

输出结果为Hello World!11111+

else if的本质是else里面套了个if,C++关键字里并没有else if

循环

for循环

格式:

for(循环开始前执行的指令;循环继续需要的条件;循环一轮结束时执行的指令){需要循环执行的指令}

比如:

for(int i = 0 ; i < 5 ; i++)
      {
            cout << i << endl;
      }

输出结果为数字0到4

当然,for的参数也可以空着:

for( ; ; )
      {
            cout << "i" << endl;
      }

会无限循环地输出字母i.

或者可以更灵活些:

int m = 0;
    for( ; m < 5; )
    {
        cout << m << endl;
        m++;
     }

输出结果同样为0到4

while循环和do while循环

格式:

while(条件){循环的指令}

个人见解:只是比for少了两个参数。

例如:

int m = 0;
    while(m < 5)
    {
        cout << m << endl;
        m++;
     }

会输出数字0到4

小技巧,不用经常改变参数一般用while循环。比如游戏中用while(running){...}比较合适。

do while与while的区别是循环会先执行一次,然后再判断条件。格式:

do{循环执行的指令}while(条件);

注意⚠️:句末有分号
比如:

int i = 0
do
     {
     cout << dooooo << endl;
     i++
     }
while(i < 1);

会输出一行dooooo

2024.8.5

流程控制语句

continue

continue只能用在循环中,代表循环在此处进入下一迭代,此次循环中不会继续执行之后的代码,比如:

for(int i =0; i<5; i++){
        if (i == 3)
            continue;
        cout << "this is " << i << endl;
    }

会输出如下结果:

this is 0
this is 1
this is 2
this is 4

可以看到3被跳过了。

break

break可以用在循环和switch中。代表在此处跳出循环。比如将上面代码中continue换成break

for(int i =0; i<5; i++){
        if (i == 3)
            break;
        cout << "this is " << i << endl;
    }

会输出:

this is 0
this is 1
this is 2

可以看到循环在3处结束了。此处breakcout前,所以不会输出第4行(数字3)。

return

return代表函数在此结束,并返回一个值,return后的代码不会被执行。
比如main函数最后的return 0;

指针

指针是用于储存内存地址(一字节)的变量,指针类型并没有实际意义,但需要与被指变量类型相同。
指针可以是无效的,比如viod* ptr = 0;void* ptr = NULL;
实际上内存并不存在地址0。

目前对指针的实际用途并不了解,待之后学习。具体内容参考:https://www.runoob.com/cplusplus/cpp-pointers.html

指针也是变量,所以指针也需要储存在内存中,自然也有对应的地址。所以可以创建指向指针的指针,也就是双指针或三指针。比如先创建一个指针void* ptr1 = NULL;则可以创建指向指针*ptr1的指针char** ptr2 = &ptr1;

值得注意的是char* ptr = &a;char *ptr = &a;都是正确的。

int m = 10;
int *ptr3 = &m;
    cout << ptr3 << endl;
    cout << *ptr3 << endl;
    cout << &ptr3 << endl;
    cout << &*ptr3 << endl;

会输出:

0x7fffffffdf94
10
0x7fffffffdfb0
0x7fffffffdf94

2024.9.9补充:使用cout输出*ptr为输出逆向引用后的指针ptr,所以结果为10。

2024.9.9

有一段时间没继续学习c++了,换电脑之后新电脑没装Linux,所以此次更新用的是Windows,可能以后一段时间都会继续用Windows。

引用

引用是一种“语法糖”,可以粗略的看作简化的指针,它可以让代码变得更简单,但其功能没有指针强大(比如:不能改变引用的变量,但指针可以改变指向的变量)。

格式:

类型& 名称 = 变量

值得注意的是,引用的&是声明引用类型的一部分,要与指针中表示变量内存地址前的&区分。
比如一个是int& ref = a;一个是int* b = &a;

引用可以理解为一个变量的别名,引用本身不是变量(不占内存),只能引用一个已存在的变量。

一个使用实例:

void plus2(int& vul) {
	vul++;
}

在这里的引用的作用是把变量传递到函数中。

如果此处声明函数时使用的是int vul而不是int& vul;,那么调用函数:plus2 (a);无法改变a的值,相当于创建了一个等于变量avul变量,并且将其值加一。

可以实现相同功能的,使用指针的代码是:

void plus1(int* vul) {
	(*vul) ++ ;
}

这里我并不清楚(*vul) ++ ;中括号的具体含义,仍需深入了解。其中*是逆向引用,用来将指针变量转换为其指向变量。

以下为实例:

#include <iostream>

using namespace std;

void plus1(int* vul) {
	(*vul) ++ ;
}

void plus2(int& vul) {
	vul++;
}

int main(){
	int a = 8;
	a++;
	cout << a << endl;
	plus1( &a );
	cout << a << endl;
	plus2(a);
	cout << a << endl;
	cout << "Hello World!" << endl;
	return 0;
}

会输出:

9
10
11
Hello World!

2024.9.11

类和结构体

在c++中,类的功能是让代码变得简洁易懂更加容易维护,实际上在写代码时并不是必须用到类,也可以用其他方法来实现特定功能,和上面的引用类似,是一种“语法糖”。类和结构体区别不大,只是类中的内容默认是“私有的”:即不能在类的外部访问。而结构体中的内容默认是公开的。

声明一个类(结构体直接把class换成struct):

class 名称{
	声明变量1;
	声明变量2;
	...
	方法1(函数)(非必须)
	...

};

注意⚠️:句末有分号

创建一个类的实例(实例是类的为对象,类中的函数称为方法):

类名称 实例名称;

调用类中的内容:

实例名称.变量或方法;

直白说就是在变量或函数前加上点和所属实例的名称,其他和正常的变量及函数用法相同。

举个例子:

class Player {
	int x, y;
	int speed;
};

这里创建了一个类,但还无法在主函数中访问它,因为其中的内容(包括变量和函数)默认是私有的,要想在主函数访问其中内容,要把需要公开的内容放在public:后。就像这样:

class Player {
public:
	int x, y;
	int speed;
};

相同的,要把结构体中的内容变为私有,则需要用到private:

如果不在类中的函数要用到类中的变量,则需要用到上面的引用将变量传入函数,像这样(这里+=的作用仍需进一步了解,记得以后看一下运算符相关的内容):

void Move (Player& player, int xa, int ya) {
	player.x += xa * player.speed;
	player.y += ya * player.speed;
}

但如果将其放进类中,变成类的方法,就可以简化很多:

class Player {
public:
	int x, y;
	int speed;

	void Move (int xa, int ya) {
		x += xa * speed;
		y += ya * speed;
	}
};

这样就不用使用引用来传入player对象到函数中了。

调用类中函数的例子:

Player player1;
player1.x = 5;
player1.y = 6;
player1.Move(2, 3);

此作者没有提供个人介绍
最后更新于 2024-09-12