C++学习笔记
C++学习笔记

C++学习笔记

Published
Author
John Liu ( github/jneeee )
 

Hello world

C++ 不同于Python的一些基本知识:
  • 引号必须是双引号
  • C++ 的缩进不是严格的,只是为了代码易读
  • 任何变量赋值前必须先声明类型
  • 用 g++ 编译后生成二进制文件可以直接执行
相同点:
  • 大小写敏感
  • ...
#include <iostream> #include <vector> #include <string> using namespace std; int main() { vector<string> msg {"Hello", "C++", "World", "from", "VS Code", "and the C++ extension!"}; for (const string& word : msg) { cout << word << " "; } cout << endl; }

1 变量

类型有 int double char string bool ...

1.1 声明(创建)一个变量

语法
type variableName = value;
示例
int myNum = 15; cout << myNum;

1.2 声明多个变量

int x = 5, y = 6, z = 50; cout << x + y + z;
为多个变量赋同一个值
int x, y, z; x = y = z = 50; cout << x + y + z;

1.4 常量

当你不想自己或别人修改一个存在的变量时,使用 const 关键词。
const int myNum = 15; // myNum will always be 15 myNum = 10; // error: assignment of read-only variable 'myNum'

2 用户输入

cin 关键词用于获取用户输入。cout 是输出。 例子:
int x; cout << "Type a number: "; // Type a number and press enter cin >> x; // Get user input from the keyboard cout << "Your number is: " << x; // Display the input value

3 数据类型

C++ 中的变量必须指定类型。
int myNum = 5; // Integer (whole number) float myFloatNum = 5.99; // Floating point number double myDoubleNum = 9.98; // Floating point number char myLetter = 'D'; // Character bool myBoolean = true; // Boolean string myText = "Hello"; // String

4 运算符

常规的加减乘除 自加自减。赋值:
int x = 10; x += 5;
比较符:
== 等于,!= 不等, 大于小于... 逻辑运算: 与:&& 或:|| 非: !

5 字符串

要使用字符串,需要:
#include <string> string greeting = "Hello";
字符串可以相加,也有对象方法 append:
string firstName = "John "; string lastName = "Doe"; string fullName = firstName.append(lastName); string fullName = firstName + " " + lastName; cout << fullName; // John Doe cout << firstName; // John Doe
fullName 是一个别名。
+ 用在数字是相加,用在字符串是串联。和 Python 一样。
字符串的长度 对象方法length().size() 功能完全一样。
string txt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; cout << "The length of the txt string is: " << txt.length();
字符串的访问。字符串也可以被index
string myString = "Hello"; cout << myString[0]; // Outputs H
不同于 Python,字符串也可以被修改(这个空间复杂度待确认):
string myString = "Hello"; myString[0] = 'J'; cout << myString; // Outputs Jello instead of Hello
如果需要在字符里打单、双引号,需要用转义字符\\
string txt = "It\\'s alright.";
常用转义字符:
\\\\ \\' \\" \\t \\n
常用的关键词 cout/string 都是来自 Omitting Namespace,默认写成std::cout ,可以用如下方式省略:
using namespace std

6 数学方法

C++ 有很多内建的数学函数

6.1 max and min

cout << max(5, 10); cout << min(5, 10);

6.2 cmath 模块

其他模块比如 sqrt/round/log 可以再 cmath 模块里找到
#include <cmath>
还有很多其他数学函数:https://www.w3schools.com/cpp/cpp_math.asp

7 布尔值

bool a = 1; bool isCodingFun = true; bool isFishTasty = false; cout << isCodingFun; // Outputs 1 (true) cout << isFishTasty; // Outputs 0 (false)
逻辑符号会生成布尔值,比如
cout << (1 > 2); // false

8 条件和 if 语句

条件就是上面提到的生成布尔值的表达式。C++ 支持如下 if 语句:
  • if
  • else
  • else if
  • switch
示例:
if (20 > 18) { cout << "20 is greater than 18"; } if (condition) { // block of code to be executed if the condition is true } else { // block of code to be executed if the condition is false } if (condition1) { // block of code to be executed if condition1 is true } else if (condition2) { // block of code to be executed if the condition1 is false and condition2 is true } else { // block of code to be executed if the condition1 is false and condition2 is false }
写在一行的条件语句:
variable = (condition) ? expressionTrue : expressionFalse;
Python:
a = 1 if True else 2

9 Switch

用 Switch 关键字从多个block中选择一个执行:
switch(expression) { case x: // code block break; case y: // code block break; default: // code block }
break 关键字会跳过剩余的 case 判断。
default 关键字在没有 case 匹配时执行。

10 while 循环

循环是在满足条件时一直执行的代码块。可以节约时间,减少错误,让代码更具可读性。
int i = 0; while (i < 5) { cout << i << "\\n"; i++; }
do...while 循环会在检查条件之前,先执行一次 block 里的代码。
int i = 0; do { cout << i << "\\n"; i++; } while (i < 5);
(注:它不支持 break 语句吗?)

11 for 循环

当你知道你要执行多少次的时候,使用 for 循环。(注:由此认为 for 是 while 循环的特殊情况)
for (statement 1; statement 2; statement 3) { // code block to be executed }
  • Statement 1 is executed (one time) before the execution of the code block.
  • Statement 2 defines the condition for executing the code block.
  • Statement 3 is executed (every time) after the code block has been executed.
循环支持嵌套。

11.1 遍历

遍历语法在C++11 之后支持。在遍历 array 或者其他数据集的时候比较有用。
int myNumbers[5] = {10, 20, 30, 40, 50}; for (int i : myNumbers) { cout << i << "\\n"; }

12 Break/continue

Break 如前文所述,可以跳出一个 switch 语句,也可以跳出一个循环。
Continue 会跳出一次循环,继续下一次。(与 python 相同)

13 数组

13.1 基本概念

用来在一个变量里面定义多个值。 声明一个数组:先定义变量类型,在定义变量名,跟着一个中括号表示它存储的对象长度。
string cars[4]; // 定义时候赋值 string cars[4] = {"Volvo", "BMW", "Ford", "Mazda"};
访问数组元素、修改元素,可以用:
string cars[4] = {"Volvo", "BMW", "Ford", "Mazda"}; cout << cars[0]; // Outputs Volvo cars[0] = "Opel"; cout << cars[0]; // Now outputs Opel instead of Volvo

13.2 数组的遍历

可以用 index 遍历,也可以 foreach 遍历:
int myNumbers[5] = {10, 20, 30, 40, 50}; for (int i = 0; i < 5; i++) { cout << myNumbers[i] << "\\n"; } for (int i : myNumbers) { cout << i << "\\n"; }

13.3 省略数组大小(声明时)

数组的大小留空,编译器会根据后面的值来定义数组大小。
string cars[] = {"Volvo", "BMW", "Ford"}; // Three arrays
对于省略数组元素,可以先声明指定大小,再一个个赋值。

13.4 获取数组的大小

通过运算符 sizeof() 获取数组大小。
int myNumbers[5] = {10, 20, 30, 40, 50}; cout << sizeof(myNumbers); // 20
上述语句输出 20 而不是 5,原因是 sizeof() 输出的单位是 bytes,而 int 类单个值大小 4 bytes。 要获取单个值大小:
int myNumbers[5] = {10, 20, 30, 40, 50}; int getArrayLength = sizeof(myNumbers) / sizeof(int); cout << getArrayLength;

13.5 数组的嵌套

和普通数组类似,需要声明数组的大小,由外到内。
string letters[2][4] = { { "A", "B", "C", "D" }, { "E", "F", "G", "H" } };
它同样能被 index 取值或修改:
cout << letters[0][2]; // Outputs "C" letters[0][0] = "Z";
遍历多维数组,只要多层嵌套循环即可。
string letters[2][4] = { { "A", "B", "C", "D" }, { "E", "F", "G", "H" } }; for (int i = 0; i < 2; i++) { for (int j = 0; j < 4; j++) { cout << letters[i][j] << "\\n"; } }
在表示网格之类的情况下,使用多维数组比较适合。

14 结构?struct

当需要把不同数据结构的变量放在一起时,使用 struct。不同于数组,struct 可以包含不同的数据类型。
使用关键字 struct 创建。并且声明它里面的每个变量的类型。在 block 的结尾,声明 struct 的名称。
struct { // Structure declaration int myNum; // Member (int variable) string myString; // Member (string variable) } myStructure; // Structure variable
访问成员(类似于 Python nametuple)
// Assign values to members of myStructure myStructure.myNum = 1; myStructure.myString = "Hello World!"; // Print members of myStructure cout << myStructure.myNum << "\\n"; cout << myStructure.myString << "\\n";
可以声明多个 struct
struct { int myNum; string myString; } myStruct1, myStruct2, myStruct3; // Multiple structure variables separated with commas
给 struct 一个名称,就能把它当做一个数据类型来用。
struct myDataType { // This structure is named "myDataType" int myNum; string myString; }; myDataType myVar;

15 引用

15.1 创建引用

引用变量是对已存在的变量的引用。用 & 创建,
string food = "Pizza"; // food variable string &meal = food; // reference to food

15.2 内存地址

& 符号可以用来创建引用,也可以用来获得内存地址。 当在 C++ 中创建变量时,一块内存地址被分配给这个变量。当我们给它赋值时,值会被存在这个内存中。
string food = "Pizza"; cout << &food; // Outputs 0x6dfed4

16 指针 Pointers

16.1 创建指针

指针是一个保存内存地址的变量。
指针也有类型,和它保存的内存地址中的变量一个类型。用 * 创建。
string food = "Pizza"; // A food variable of type string string* ptr = &food; // A pointer variable, with the name ptr, that stores the address of food // Output the value of food (Pizza) cout << food << "\\n"; // Output the memory address of food (0x6dfed4) cout << &food << "\\n"; // Output the memory address of food with the pointer (0x6dfed4) cout << ptr << "\\n";

16.2 Dereference (指针取值)

* 取到指针内存地址所指向的值。
string food = "Pizza"; // Variable declaration string* ptr = &food; // Pointer declaration // Reference: Output the memory address of food with the pointer (0x6dfed4) cout << ptr << "\\n"; // Dereference: Output the value of food with the pointer (Pizza) cout << *ptr << "\\n";

16.3 修改指针

你可以修改指针的值,但注意这同时也会修改所指内存的值(the value of the original variable)
string food = "Pizza"; string* ptr = &food; // Output the value of food (Pizza) cout << food << "\\n"; // Output the memory address of food (0x6dfed4) cout << &food << "\\n"; // Access the memory address of food and output its value (Pizza) cout << *ptr << "\\n"; // Change the value of the pointer *ptr = "Hamburger"; // Output the new value of the pointer (Hamburger) cout << *ptr << "\\n"; // Output the new value of the food variable (Hamburger) cout << food << "\\n";

17 函数

函数是一个只在调用时才会执行的代码块 (block),

17.1 创建函数

C++ 提供了一些预定义的函数,比如 main(),你也可以自定义:
void myFunction() { // code to be executed }
其中:
  • myFunction 是函数名
  • void 表示这个函数没有返回值

17.2 调用函数

调用函数使用 ();
int main() { myFunction(); // call the function return 0; }
如果 myFunction 函数在 main 之后被定义,则会报错。 函数定义分为两个部分 声明 和 定义:
void myFunction() { // declaration // the body of the function (definition) }
为解决定义顺序问题,你经常会看到声明放在 main 的前面,定义放在后面。
// Function declaration void myFunction(); // The main method int main() { myFunction(); // call the function return 0; } // Function definition void myFunction() { cout << "I just got executed!"; }

18 函数入参

18.1 入参写法

void functionName(parameter1, parameter2, parameter3) { // code to be executed }

18.2 缺省参数

= 定义缺省时的参数值:
void myFunction(string country = "Norway") { cout << country << "\\n"; } int main() { myFunction("Sweden"); myFunction(); return 0; }

18.3 多个参数

void myFunction(string fname, int age) { cout << fname << " Refsnes. " << age << " years old. \\n"; } int main() { myFunction("Liam", 3); myFunction("Jenny", 14); myFunction("Anja", 30); return 0; }

18.4 返回值关键字

void 关键字声明函数没有返回值。你可以指定其他返回值类型。
int myFunction(int x, int y) { return x + y; } int main() { int z = myFunction(5, 3); // store return value in z cout << z; return 0; }

18.5 传递引用 (reference)

当你需要函数修改入参时,传递引用。
void swapNums(int &x, int &y) { int z = x; x = y; y = z; } int main() { int firstNum = 10; int secondNum = 20; cout << "Before swap: " << "\\n"; cout << firstNum << secondNum << "\\n"; // Call the function, which will change the values of firstNum and secondNum swapNums(firstNum, secondNum); cout << "After swap: " << "\\n"; cout << firstNum << secondNum << "\\n"; return 0; }

18.6 传递数组

当你调用时,只用写 myFunction(myNumbers);,但函数声明时要写成 int myNumbers[5]
void myFunction(int myNumbers[5]) { for (int i = 0; i < 5; i++) { cout << myNumbers[i] << "\\n"; } } int main() { int myNumbers[5] = {10, 20, 30, 40, 50}; myFunction(myNumbers); return 0; }

19 函数重载

通过函数重载,不同的函数可以有同一个名称和不同的参数。
int myFunction(int x) float myFunction(float x) double myFunction(double x, double y)
(函数定义得重新写)

20 递归

递归是在函数里面调用自身。
int sum(int k) { if (k > 0) { return k + sum(k - 1); } else { return 0; } } int main() { int result = sum(10); cout << result; return 0; }

21 面向对象的程序设计

过程式编程是关于编写对数据执行操作的过程或函数,而面向对象编程是关于创建同时包含数据和函数的对象。
和面向过程相比,面向对象有如下的优势:
  • 面向对象更容易执行
  • 提供了清晰的架构
  • 让代码简洁,容易改动
  • 可以更少代码更短时间创建可复用程序

22 类和对象

C++ 是个面向对象的编程语言。

22.1 创建类

class MyClass { // The class public: // Access specifier int myNum; // Attribute (int variable) string myString; // Attribute (string variable) }; // endwith ; int main() { MyClass myObj; // Create an object of MyClass // Access attributes and set values myObj.myNum = 15; myObj.myString = "Some text"; // Print attribute values cout << myObj.myNum << "\\n"; cout << myObj.myString; return 0; }

23 类方法

类方法是属于类的函数,有两种方法定义:
  • 类的里面
  • 类的外面
class MyClass { // The class public: // Access specifier void myMethod() { // Method/function defined inside the class cout << "Hello World!"; } }; int main() { MyClass myObj; // Create an object of MyClass myObj.myMethod(); // Call the method return 0; }
要在类的外面定义函数,你要现在类里面声明,再在类外面定义。用 :: 分开类名和函数名:
class MyClass { // The class public: // Access specifier void myMethod(); // Method/function declaration }; // Method/function definition outside the class void MyClass::myMethod() { cout << "Hello World!"; } int main() { MyClass myObj; // Create an object of MyClass myObj.myMethod(); // Call the method return 0; }

24 构造函数 Constructors

构造函数是 C++ 的一个特殊方法,在对象被创建时执行。要创建一个构造函数:用类名同名,跟一个 ()
class MyClass { // The class public: // Access specifier MyClass() { // Constructor cout << "Hello World!"; } }; int main() { MyClass myObj; // Create an object of MyClass (this will call the constructor) return 0; }
构造函数的入参和缺省与普通函数类似。

25 访问说明符 Access specifier