1. 内联 inline
c 里面的宏嵌入是源码嵌入,内联是二进制嵌入,二进制代替多次调用;
内联一般用于多次调用的小函数,用空间换时间;
注意:递归函数无法作内联,递归是自己调自己,所以无法自己嵌自己;
通过 inline 关键字,可以建议编译器对函数进行内联,但是仅仅是建议,编译器可以不执行;
inline void foo(int x) {...}
现在的编译器会自己判断是否需要内联;
2. 动态内存分配 new/delete(操作符)
c 里面用下面几个函数动态分配内存,位于堆里面,c++ 同样可以使用,需要包含头文件 #include <cstdlib>
malloc(不清零)/calloc(清零)/realloc/free
int *p = (int *)malloc(1 * sizeof(int)); // c++里不推荐使用
new 和 malloc 区别:
1)new 是运算符,malloc 是函数;
2)new 最终还是调用 malloc 分配内存;
3)malloc 仅仅是分配内存,new 还调用构造函数;
c++里主要用下面函数进行内存分配和释放:(不用包含任何头文件)
new/delete :对单个变量进行内存分配/释放,上面那段 malloc 代码可以写为:
int *p = new int;
delete p;
p = NULL;
也可以如下初始化:(有待验证)
int *p = new int (56); // 对p进行赋初值
下面两种变量初始化方式都正确:
int i = 10;
int i(10);
一般情况下,我们 delete 完了,就要把指针清零置空;
int *p = new int;
delete p;
*p = 2000; // 这种情况下,p属于野指针,无法确定结果,属于未定义类型;
int *p = new int;
delete p;
p = NULL;
*p = 2000; // 这种情况下,p为零,结果确定,返回段错误;
对数组进行内存分配/释放:new[]/delete[]:
p = new int [10];
delete[] p; // 如果此处不带[ ],那么结果不确定,属于未定义;多维数组也用这条语句释放,不用多加[ ]
p = NULL;
注意:
delete[] p; 相当于: delete (p-4);
记着,这里 p 前面有 4 个字节用于存放数组大小;
3. 定位分配:在指定位置分配内存空间;(了解)
并不是所有 new 分配出来的空间都在堆里面;
char buf[4] = {0x12, 0x34, 0x99, 0x23}; // buf里面放了四个数,buf 位于栈里面
int *p = new (buf) int; // 在 buf 里面分配一个 int 空间给 p,所以这个空间在栈里面
delete p; // error,段错误,栈不需要释放
4. 引用即别名;
int a = 20;
int &b = a; // 引用,b就是a的别名
b = 10; // 此时 a 值为10
引用必须初始化,且非常引用必须用变量初始化;
只有常引用可以用常量初始化;
一旦初始化,就不能再引用其他变量;
int &b; // error
int &b = 1000; // error
const int &b = 100; // ok
引用是在底层其实就是用指针来实现的。
c++ 和 c 相比,就多加了两个变量,一个是布尔,另一个是引用;
5. 引用应用场景:
1)引用型参数:
a.修改实参
c 里面的宏嵌入是源码嵌入,内联是二进制嵌入,二进制代替多次调用;
内联一般用于多次调用的小函数,用空间换时间;
注意:递归函数无法作内联,递归是自己调自己,所以无法自己嵌自己;
通过 inline 关键字,可以建议编译器对函数进行内联,但是仅仅是建议,编译器可以不执行;
inline void foo(int x) {...}
现在的编译器会自己判断是否需要内联;
2. 动态内存分配 new/delete(操作符)
c 里面用下面几个函数动态分配内存,位于堆里面,c++ 同样可以使用,需要包含头文件 #include <cstdlib>
malloc(不清零)/calloc(清零)/realloc/free
int *p = (int *)malloc(1 * sizeof(int)); // c++里不推荐使用
new 和 malloc 区别:
1)new 是运算符,malloc 是函数;
2)new 最终还是调用 malloc 分配内存;
3)malloc 仅仅是分配内存,new 还调用构造函数;
c++里主要用下面函数进行内存分配和释放:(不用包含任何头文件)
new/delete :对单个变量进行内存分配/释放,上面那段 malloc 代码可以写为:
int *p = new int;
delete p;
p = NULL;
也可以如下初始化:(有待验证)
int *p = new int (56); // 对p进行赋初值
下面两种变量初始化方式都正确:
int i = 10;
int i(10);
一般情况下,我们 delete 完了,就要把指针清零置空;
int *p = new int;
delete p;
*p = 2000; // 这种情况下,p属于野指针,无法确定结果,属于未定义类型;
int *p = new int;
delete p;
p = NULL;
*p = 2000; // 这种情况下,p为零,结果确定,返回段错误;
对数组进行内存分配/释放:new[]/delete[]:
p = new int [10];
delete[] p; // 如果此处不带[ ],那么结果不确定,属于未定义;多维数组也用这条语句释放,不用多加[ ]
p = NULL;
注意:
delete[] p; 相当于: delete (p-4);
记着,这里 p 前面有 4 个字节用于存放数组大小;
3. 定位分配:在指定位置分配内存空间;(了解)
并不是所有 new 分配出来的空间都在堆里面;
char buf[4] = {0x12, 0x34, 0x99, 0x23}; // buf里面放了四个数,buf 位于栈里面
int *p = new (buf) int; // 在 buf 里面分配一个 int 空间给 p,所以这个空间在栈里面
delete p; // error,段错误,栈不需要释放
4. 引用即别名;
int a = 20;
int &b = a; // 引用,b就是a的别名
b = 10; // 此时 a 值为10
引用必须初始化,且非常引用必须用变量初始化;
只有常引用可以用常量初始化;
一旦初始化,就不能再引用其他变量;
int &b; // error
int &b = 1000; // error
const int &b = 100; // ok
引用是在底层其实就是用指针来实现的。
c++ 和 c 相比,就多加了两个变量,一个是布尔,另一个是引用;
5. 引用应用场景:
1)引用型参数:
a.修改实参