C++核心编程总结(1)基础知识
一、C++定义常量两种方式
- #define 宏常量:
#define 常量名 常量值
通常在文件上方定义,表示一个常量。 - const修饰的变量
const 数据类型 常量名 = 常量值
通常在变量定义前加关键字const,修饰该变量为常量,不可修改。
#define day 7;
const int month = 12;
二、三目运算符
作用: 通过三目运算符实现简单的判断
语法:表达式1 ? 表达式2 :表达式3
解释:
如果表达式1的值为真,执行表达式2,并返回表达式2的结果;
如果表达式1的值为假,执行表达式3,并返回表达式3的结果。
c = a > b ? a : b;
三、各类语句
break语句
- 出现在<mark>switch</mark>条件语句中,作用是终止case并跳出switch;
- 出现在<mark>循环语句</mark>中,作用是跳出当前的循环语句;
- 出现在<mark>嵌套循环</mark>中,跳出最近的内层循环语句;
continue语句
作用:在<mark>循环语句</mark>中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环
注意:continue并没有使整个循环终止,而break会跳出循环。
goto语句
作用:可以无条件跳转语句;
语法 :goto 标记;
解释:如果标记的名称存在,执行到goto语句时,会跳转到标记的位置。
四、冒泡排序
作用: 最常用的排序算法,对数组内元素进行排序。
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个;
- 对每一对相邻元素做同样的工作,执行完毕后,找到第一个最大值;
- 重复以上的步骤,每次比较次数-1,直到不需要比较。
#include<iostream>
using namespace std;
int main() {
int arr[] = {
1,4,8,6,10,3,5,7,9};
int num = sizeof(arr) / sizeof(arr[0]);
int temp;
//总共排序的轮数=元素个数-1
for (int i = 0; i < num - 1; i++)
{
//内层循环对比 次数=元素个数-当前轮数-1
for (int j = 0; j < num - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
for (int i = 0; i < num; i++)
{
cout << arr[i] << " ";
}
cout << endl;
system("pause");
return 0;
}
注意:理解冒泡排序的原理:
排序了多少轮:总共排序的轮数=元素个数-1
内层循环对比:次数=元素个数-当前轮数-1
使用两个for循环嵌套即可实现。
五、指针(重要)
作用: 可以通过指针间接访问内存,可以利用指针变量保存地址。
指针变量定义语法: 数据类型 * 变量名;
所有指针类型在32位操作系统下是4个字节。
空指针:指针变量指向内存中编号为0的空间,可用来始化指针变量。
注意:空指针指向的内存是不可以访问的。
- const修饰指针
const修饰指针有三种情况:
- const修饰指针 — 常量指针;
- const修饰常量 — 指针常量;
- const即修饰指针,又修饰常量。
- const修饰的是指针,指针指向可以改,指针指向的值不可以更改。
const int * p1 = &a;
- const修饰的是常量,指针指向不可以改,指针指向的值可以更改。
int * const p2 = &a;
- const既修饰指针又修饰常量。
const int * const p3 = &a;
常量指针可用在函数当中,防止实参改变的误操作,如:
//学生结构体定义
struct student
{
//成员列表
string name; //姓名
int age; //年龄
int score; //分数
};
//const使用场景
void printStudent(const student *stu) //加const防止函数体中的误操作
{
//stu->age = 100; //操作失败,因为加了const修饰
cout << "姓名:" << stu->name << " 年龄:" << stu->age << " 分数:" << stu->score << endl;
}
int main() {
student stu = {
"张三",18,100 };
printStudent(&stu);
system("pause");
return 0;
}
六、内存分区
- 程序运行前:
-
代码区:共享、只读;
代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可;代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令。 -
全局区:存放全局变量、静态变量、常量(字符串常量、const修饰的全局常量),数据在程序结束后由操作系统释放。
- 程序运行后:
- 栈区:存放函数的参数值、局部变量等,注意:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放;
- 堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收,利用new在堆区开辟内存。
开辟内存:new关键字,如:
int* a = new int(10);
int* arr = new int[10];//开辟数组
释放内存:delete关键字,如:
delete p;
delete[] arr;//释放数组
开辟变量:
int* func()
{
int* a = new int(10);
return a;
}
int main() {
int *p = func();
cout << *p << endl;
cout << *p << endl;
//利用delete释放堆区数据
delete p;
//cout << *p << endl; //报错,释放的空间不可访问
system("pause");
return 0;
}
开辟数组:
//堆区开辟数组
int main() {
int* arr = new int[10];
for (int i = 0; i < 10; i++)
{
arr[i] = i + 100;
}
for (int i = 0; i < 10; i++)
{
cout << arr[i] << endl;
}
//释放数组 delete 后加 []
delete[] arr;
system("pause");
return 0;
}
七、引用
引用就是给变量起别名,但其本质是一个指针常量。
<mark>引用做函数参数:</mark>
函数传参时,可以利用引用让形参修饰实参,可简化指针修改实参。值传递、地址传递、引用传递比较:
- 值传递
值传递中形参变化而实参不变。
void mySwap01(int a, int b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int a = 10;
int b = 20;
mySwap01(a, b);
cout << "a:" << a << " b:" << b << endl;
system("pause");
return 0;
}
- 地址传递
地址传递形参、实参均改变。
void mySwap02(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int a = 10;
int b = 20;
mySwap02(&a, &b);
cout << "a:" << a << " b:" << b << endl;
system("pause");
return 0;
}
- 引用传递
引用传递形参、实参均改变,效果和地址传递一样,好理解。
void mySwap03(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int a = 10;
int b = 20;
mySwap03(a, b);
cout << "a:" << a << " b:" << b << endl;
system("pause");
return 0;
}
总结:通过引用参数产生的效果同按地址传递是一样的。引用的语法更清楚简单。
<mark>函数重载:</mark>
作用:函数名可以相同,提高复用性
函数重载满足条件:
- 同一个作用域下
- 函数名称相同
- 函数参数类型不同 或者 个数不同 或者 顺序不同
注意: 函数的返回值不可以作为函数重载的条件。