C++ 自学笔记
注释
typedef
(给类型取别名)
枚举类型(enum)
变量
- 变量先声明(指定类型和名字),再定义(指定初始值)。
- 变量作用域:
- 在函数或一个代码块内部声明的变量,称为局部变量。
- 在函数参数的定义中声明的变量,称为形式参数。
- 在所有函数外部声明的变量,称为全局变量。
- 不应该把
true
的值看成1
,把false
的值看成0
。
常量
定义常量(一般用大写字母表示):
- 使用
#define
预处理器:#define LENGTH 10
(仅仅是简单的替换) - 使用
const
关键字:const int LENGTH = 10;
(const
类型的对象在程序执行期间不能被修改)
关键字
static
关键字:- 当
static
修饰局部变量时,可以在程序的生命周期内保持局部变量的存在,而不需要在每次进入和离开作用域时对它进行创建和销毁。因此,使用static
修饰函数中的局部变量可以在不断地调用这个函数之间保持这个局部变量的值。 - 当
static
修饰全局变量时,会使变量的作用域限制在声明它的文件内,这样就可以在不同的文件里定义同名的全局变量了。
- 当
extern
关键字:- 提供一个全局变量的引用,全局变量对所有文件都是可见的。
- 当有多个文件且定义了一个可以在其他文件中使用的全局变量或函数时,可以在其他文件中使用
extern
来得到已定义的变量或函数的引用。即,extern
用来在另一个文件中声明一个全局变量或函数。 - 用于当有多个文件共享相同的全局变量或函数时。
运算符
- 取模运算符(
%
):得到整除后的余数。 - 逻辑运算符:
- 逻辑与(
&&
) - 逻辑或(
||
) - 逻辑非(
!
)
- 逻辑与(
- 杂项运算符:
sizeof()
:获取各种数据类型的大小。- 条件运算符(
? :
):Exp1 ? Exp2 : Exp3;
(如果 Exp1 为真,则计算 Exp2 的值;如果 Exp1 为假,则计算 Exp3 的值。) - 成员运算符(
.
【点】 和->
【箭头】):直接访问成员时,使用点运算符;通过指针访问成员时,使用箭头运算符。1
2strcpy(emp.first_name, "zara");
strcpy(p_emp->first_name, "zara"); - 强制转换运算符:
(type) expression
- 指针运算符:
- 取地址运算符(
&
):返回操作数的内存地址。 - 间接寻址运算符(
*
):返回操作数所指定地址的变量的值。调用时变量前加
&
:返回该变量的地址。声明时变量前加
类型*
:该指针变量表示另一个普通变量的地址(int* a;
)。调用时变量前加
*
:表示取该地址的内容。声明时变量前加
类型**
:该二级指针变量表示另一个一级类型*
指针变量的地址。(int** a;
)
- 取地址运算符(
循环
- 基于范围的
for
循环(C++11):1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25int my_array[5] = { 1, 2, 3, 4, 5 };
// 不会改变 my_array 数组中元素的值
// x 将使用 my_array 数组的副本
for (int x : my_array)
{
x *= 2;
cout << x << endl;
}
// 会改变 my_array 数组中元素的值
// 符号 & 表示 x 是一个引用变量,将使用 my_array 数组的原始数据
// 引用是已定义的变量的别名
for (int& x : my_array)
{
x *= 2;
cout << x << endl;
}
// 还可直接使用初始化列表
for (int x : { 1, 2, 3, 4, 5 })
{
x *= 2;
cout << x << endl;
} - 无限循环:
while (true)
for ( ; ; )
数组
- 数组名是指向数组中第一个元素的常量指针。
- 可以通过指定不带索引的数组名来传递一个指向数组的指针。传递数组给一个函数,数组类型自动转换为指针类型,因此传递的实际是地址。
- 不允许返回一个完整的数组作为函数的参数。但是,可以通过指定不带索引的数组名来返回一个指向数组的指针。
- 不支持在函数外返回局部变量的地址,除非在函数内定义局部变量为
static
变量。
字符串
- C 风格字符串:
- 字符串实际上是使用
null
字符'\0'
终止的一维字符数组。1
2
3char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
// 等价于
char greeting[] = "Hello"; - 其实,不需要把
null
字符放在字符串常量的末尾。编译器在初始化数组时,会自动把'\0'
放在字符串的末尾。
- 字符串实际上是使用
- C++ 中的 string 类
指针
使用指针:
1
2
3
4
5
6int var = 20;
int* ip; // 定义一个指针变量
ip = &var; // 把变量地址赋值给指针
cout << "Value of *ip variable: ";
cout << *ip << endl; // 访问指针变量中可用地址的值空指针:
int* ptr = NULL;
使用指针操作数组:
1
2
3
4
5
6
7
8
9
10
11
12const int MAX = 3;
int var[MAX] = { 10, 100, 1000 };
int* ptr = var; // var 是一个指向数组开头的常量,不能直接 var++
while (ptr <= &var[MAX - 1]) // 指针的比较
{
cout << *ptr << endl;
ptr++; // 递增一个指针
}
*(var + 2) = 10000;
cout << var[2] << endl;指针数组:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18const int MAX = 4;
// 用一个指向字符的指针数组来存储一个字符串列表
// 指针数组的每个元素存储的是每个字符串数组的首字母的地址
const char* names[MAX] = {
"Zara Ali",
"Hina Ali",
"Nuha Ali",
"Sara Ali",
};
for (int i = 0; i < MAX; i++)
{
cout << &names[i] << endl; // 地址是连续的(相差4)
cout << "Value of names[" << i << "] = ";
cout << names[i] << endl; // 整个字符串数组
cout << names[i][0] << endl; // 字符串数组的首字母
}指向指针的指针(多级间接寻址):
当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。
1
2
3
4
5
6
7int var = 123;
int* ptr = &var;
int** pptr = &ptr;
cout << "var值为:" << var << endl;
cout << "*ptr值为:" << *ptr << endl;
cout << "**pptr值为:" << **pptr << endl;传递指针给函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19double getAverage(int* arr, int size)
{
int sum = 0;
for (int i = 0; i < size; i++)
{
sum += arr[i];
}
return double(sum) / size;
}
int main()
{
int balance[4] = { 1, 2, 3, 4 };
cout << "Average value is:" << getAverage(balance, 4) << endl;
return 0;
}从函数返回指针:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31#include <iostream>
#include <ctime>
using namespace std;
int* getRandom() // 生成和返回随机数的函数
{
static int r[10]; // C++不支持在函数外返回局部变量的地址,除非定义局部变量为static变量。
srand((unsigned)time(NULL)); // 设置种子
for (int i = 0; i < 10; i++)
{
r[i] = rand();
cout << r[i] << endl;
}
return r;
}
int main()
{
int* p = getRandom();
for (int i = 0; i < 10; i++)
{
cout << "*(p+" << i << "):";
cout << *(p + i) << endl;
}
return 0;
}
引用
引用和指针的区别:
- 不存在空引用。引用必须连接到一块合法的内存。
- 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
- 引用必须在创建时被初始化。指针可以在任何时间被初始化。
创建引用:
1
2int i = 10;
int& r = i;把引用作为函数参数:
比传一般的参数更安全。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25void swap(int& x, int& y)
{
int temp;
temp = x;
x = y;
y = temp;
return;
}
int main()
{
int a = 100;
int b = 200;
cout << a << endl;
cout << b << endl;
swap(a, b);
cout << a << endl;
cout << b << endl;
return 0;
}把引用作为函数返回值:
通过使用引用来替代指针,会使 C++ 程序更容易阅读和维护。C++ 函数可以返回一个引用,方式与返回一个指针类似。
当函数返回一个引用时,则返回一个指向返回值的隐式指针。这样,函数就可以放在赋值语句的左边。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25double vals[5] = { 10.1, 12.6, 33.1, 24.1, 50.0 };
double& setValues(int i)
{
return vals[i];
}
int main()
{
for (int i = 0; i < 5; i++)
{
cout << vals[i] << endl;
}
// 当函数返回一个引用时,则返回一个指向返回值的隐式指针。这样,函数就可以放在赋值语句的左边。
setValues(1) = 20.23;
setValues(3) = 70.8;
for (int i = 0; i < 5; i++)
{
cout << vals[i] << endl;
}
return 0;
}
结构体
- 定义结构体:
1
2
3
4
5
6
7struct Books // 结构体类型的名称
{
char title[50];
char author[50];
char subject[100];
int book_id;
} book; // 可以指定一个或多个结构变量,这是可选的。 - 访问结构成员:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43#include <iostream>
#include <string>
using namespace std;
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
int main()
{
Books Book1;
Books Book2;
// Book1 详述
strcpy_s(Book1.title, "C++ 教程");
strcpy_s(Book1.author, "Runoob");
strcpy_s(Book1.subject, "编程语言");
Book1.book_id = 12345;
// Book2 详述
strcpy_s(Book2.title, "CSS 教程");
strcpy_s(Book2.author, "Runoob");
strcpy_s(Book2.subject, "前端技术");
Book2.book_id = 12346;
// 输出 Book1 信息
cout << "第一本书标题 : " << Book1.title << endl;
cout << "第一本书作者 : " << Book1.author << endl;
cout << "第一本书类目 : " << Book1.subject << endl;
cout << "第一本书 ID : " << Book1.book_id << endl;
// 输出 Book2 信息
cout << "第二本书标题 : " << Book2.title << endl;
cout << "第二本书作者 : " << Book2.author << endl;
cout << "第二本书类目 : " << Book2.subject << endl;
cout << "第二本书 ID : " << Book2.book_id << endl;
return 0;
} - 结构体作为函数参数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45#include <iostream>
#include <string>
using namespace std;
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
void printBook(struct Books book)
{
cout << "书标题 : " << book.title << endl;
cout << "书作者 : " << book.author << endl;
cout << "书类目 : " << book.subject << endl;
cout << "书 ID : " << book.book_id << endl;
}
int main()
{
Books Book1;
Books Book2;
// Book1 详述
strcpy_s(Book1.title, "C++ 教程");
strcpy_s(Book1.author, "Runoob");
strcpy_s(Book1.subject, "编程语言");
Book1.book_id = 12345;
// Book2 详述
strcpy_s(Book2.title, "CSS 教程");
strcpy_s(Book2.author, "Runoob");
strcpy_s(Book2.subject, "前端技术");
Book2.book_id = 12346;
// 输出 Book1 信息
printBook(Book1);
// 输出 Book2 信息
printBook(Book2);
return 0;
} - 指向结构的指针:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45#include <iostream>
#include <string>
using namespace std;
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
void printBook(struct Books* book)
{
cout << "书标题 : " << book->title << endl;
cout << "书作者 : " << book->author << endl;
cout << "书类目 : " << book->subject << endl;
cout << "书 ID : " << book->book_id << endl;
}
int main()
{
Books Book1;
Books Book2;
// Book1 详述
strcpy_s(Book1.title, "C++ 教程");
strcpy_s(Book1.author, "Runoob");
strcpy_s(Book1.subject, "编程语言");
Book1.book_id = 12345;
// Book2 详述
strcpy_s(Book2.title, "CSS 教程");
strcpy_s(Book2.author, "Runoob");
strcpy_s(Book2.subject, "前端技术");
Book2.book_id = 12346;
// 通过传 Book1 的地址来输出 Book1 信息
printBook(&Book1);
// 通过传 Book2 的地址来输出 Book2 信息
printBook(&Book2);
return 0;
} - 使用
typedef
进行简化:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15typedef struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
}Books;
void printBook(Books* book)
{
cout << "书标题 : " << book->title << endl;
cout << "书作者 : " << book->author << endl;
cout << "书类目 : " << book->subject << endl;
cout << "书 ID : " << book->book_id << endl;
}
C++ 自学笔记
https://roachlin.github.io/2021-12-08-self-learn-cpp/