【语言学习】cpp学习 - hippowc/hippowc.github.io GitHub Wiki
概述
C++ 是一种静态类型的、编译式的语言,支持多种范式,目前常用C++17、C++20,它的多模式使其学起来复杂,可以将其看做四种语言的组合:
- A better C:可以当做C语言来使用,且是一个更易用的C
- C with Classes:支持class,封装继承多态
- template metaprogramming:模板元编程
- Standard Template Library(STL):标准模板库,从根本上说,STL 是一些容器、算法和其他一些组件的集合
数据类型
基础数据类型
- bool/char/int/float/double/void/wchar_t
- 类型修饰符:signed/unsigned, short/long
- typedef: 类型别名
typedef int feet;
feet distance;
指针
- 指针操作
// 指针声明
int *a;
// 赋值
*a = 10;
// 声明并赋值时,右值需要时地址
int b = 10;
int *c = &b;
// 地址赋值
c = &b;
// 指针使用,打印c指向的值
cout << *c << endl;
引用类型
- 引用必须初始化,引用只能绑定在对象上,而不能与字面值或某个表达式的计算结果绑定在一起,类型要严格匹配
int a = 3;
// b是a的一个引用,或者叫别名,引用必须在定义的时候初始化,并且不能重新赋值
int &b = a;
- 常量引用:初始化常量引用时允许用任意表达式作为初始值
const int &r2 = 42;
变量、常量与函数
变量
- 局部变量:在函数或代码块内部声明
- 全局变量:在所有函数外部声明
- 形式参数:在函数入参声明
常量
固定值,在程序执行期间不会改变。
// 预处理器
#define LENGTH 10
// const
const int LENGTH = 10;
函数
- 声明
int foo();
- 实现
int foo() {
xx;
}
函数参数
- 传值:形参是实参的拷贝,改变形参的值并不会影响外部实参的值
- 传引用:形参相当于是实参的“别名”,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。
// 实现
void foo(int & bar){
int temp = bar; // 跟正常变量使用一样,只是会改变原有值
bar = 1;
}
// 调用
int a = 0;
foo(a)
- 传指针:形参为指向实参地址的指针
// 实现
void foo(int *bar) {
int temp = *bar; // 使用指针的方式
*bar = 1; // 给指针中地址赋值
}
// 使用
int a = 0;
foo(&a); // 取a的地址
类
类定义
类的变量和函数的声明和实现可以分开
class c_name {
access specifier:
// 构造函数声明
c_name();
// 析构函数声明,在销毁对象的时候调用
~c_name();
// 成员变量声明
int v;
// 函数声明
double get(void);
}
// 函数定义
double c_name::get(void){
...
}
初始化
初始化顺序:
- 使用初始化列表中数据进行初始化
- 初始化类成员变量,使用默认方式赋值
- 执行构造函数的赋值操作
初始化的方式:
- 在构造函数内赋值
- 使用初始化列表:常量成员,引用类型,无默认构造函数的类必须使用初始化列表
class c_name {
public:
int a;
int b;
c_name():a(0),b(1){}
}
内存分配与释放
- 通常定义变量或者对象,编译器在编译时都可以根据该变量或对象的类型知道所需内存空间的大小,从而系统在适当的时候为他们分配确定的存储空间,这种内存分配被称为静态存储分配。
- 有些操作对象只有在程序运行时才能确定,这样编译器在编译时就无法为他们预定存储空间,只能在程序运行时,系统根据运行时的要求进行内存分配,这种方法称为动态内存分配。
- 所有动态存储分配都在堆区中进行。
- ClassName object;在Stack栈里面分配空间,自动释放。
- new ClassName();在heap堆里面分配空间,要手动释放。
// 使用new分配内存
type * p_var = new type;
//分配内存,但未初始化
int * a = new int;
type * p_var = new type(init);
//分配内存时,将 *a 初始化为 8
int * a = new int(8);
type *p_var = new type [size];
//分配了3个int大小的连续内存块,但未初始化
int * a = new int[3] ;
// 使用delete释放内存
删除单变量地址空间
int *a = new int;
delete a;//释放单个int的空间
删除数组空间
int *a = new int[5];
delete []a;//释放int数组空间
动态内存分配场景
当需要动态分配内存时,最佳实践:
- 使用具有RAII特性的类型(例如标准容器)
- 智能指针