1.内联函数与宏定义:
宏定义预处理阶段简单直接替换:比如#define max(a,b) a>b?a:b;
如果使用 max(a++,b)
会产生歧义:a++ >b?a++:b;
a自增两次。
解决宏定义产生的歧义:内联函数/内置函数
inline int max(int a,int b){
a>b?a:b
}
会直接替换函数调用的代码,产生很多复制,不如函数调用好。
plus:程序编译:
1) 预处理:程序展开和替换。.h
文件展开到#include中,以及宏替换等,但不做运算功能。
2) 编译:高级语言编译成汇编语言,程序-》目标模块
3) 链接:目标模块和库函数链接,形成装入模块。
4) 装入:最终模块装入内存
2. 三大特性:封装继承多态。
封装:实现高内聚,低耦合,模块化,更容易维护。
多态:1.继承 2 重写 3.父类引用指向子类对象(Object *obj = Cat cat()
)
3. 重载:
函数名同,参数不同。区别重写。
4. 重写(多态):父类某个函数加了virtual(父类为虚函数),子类定义完全一致的函数。
虚函数于纯虚函数是由区别的:虚函数需要加上代码定义,纯虚函数不需要,如果存在纯虚函数是抽象类,只能继承。
当基类产生继承和多态时,基类的析构函数为虚函数
。不然在父类指针指向子类对象时,delete只会调用父类而不会调用子类。
5. struct、class区别:
struct:成员默认public;class:默认private。
class和可以定义模板参数,但是struct不支持。
6.泛型算法algorithm
replace:将vec中的0都替换成22
replace(vec.begin(),vec.end(),0,22);
lambda:[(&引用)变量](形参) -> return type{};
[ ]里面是这个函数需要捕获局部变量、(这个局部变量在之前有定义)()是这个函数的形参,接下来是返回类型,函数体部分。
7. 复制构造函数
构造函数的一种,只有一个参数(本类的引用)。可以时const(常用), 也可以非const。
作用:使用一个已经存在的对象取初始化同类的一个新对象。
调用情况:1.类的一个对象去初始化(仅初始化) 该类的里那个一个对象;A b(a); A b=a; 两条等价
2.函数的形参为类的对象;3.函数的返回值是类的对象。
默认的复制构造函数:元素的对应复制,两个对象指向同一个地址内存。(浅复制:动态释放内存时,内存泄漏,因为释放了两次)A a; A b(a);
浅复制:如果要确保实参的值不会改变,又希望避免复制构造函数带来的开销,解决办法就是将形参声明为对象的 const 引用。
自定义复制构造函数:深复制,拷贝构造函数需要建立一个新对象
构造函数可以被重载,析构函数有且只有一个,且没有参数,不可以被重载。
class A{
public:
type t1,t2;
A(type _t1,type _t2){
t1=_t1;
t2=_t2;
}
A(const A& a){ // 深复制 const更好:可以接收常量对象
t1=a.t1;
t2=a.t2;
}
}
8.const:“常”
char*
:“读、写”权限;const char*
:“只读”权限“
const 与 指针变量
:
const离变量名 近 修饰指针变量 p1,p2。
const里变量名 远 修饰指针指向的数据。
1.const离变量名 近
const int *p1;
int const *p2; // p1\p2可以修改指向不同的数据,但其数据并能被修改。
2.const离变量名 远
int* const p; //指针只读,p不能被修改
const 与 函数形参
:
形参若是指针,可防止函数内部修改指针指向的数据。比如size_t strlen(const char* str)-(查找字符串长度)。
作用:防止误操作修改变量;提示用户函数不会修改提供的变量。
const:修饰成员变量和成员函数,变成常类型,数据不再被修改。
const char* get() 返回值时不能被修改的const类型。
char* get() const "只读"取成员变量的值,而不能修改。
1.new,delete ; malloc,free;
分别为两对:new-delete 有构造析构函数;malloc-free没有
2. 引用:
引用作为形参不需要分配存储空间,(提高程序效率)。如果又不希望变量在函数内部改变,加const。
3.C++内存区域:
(delete、free释放)堆区:new,malloc开辟的
(函数结束释放)栈区:局部变量
(程序退出释放)静态存储区:全局变量
局部变量会屏蔽全局变量,如果需要在同名的情况下使用全局变量,需要使用域运算符(::)。
4.指针数组与数组指针:
数组指针(行|组指针) int (*p)[n]
, ()优先级高,说明p是指针,指向一个整型的长度为n的一维数组。p+1时,p跨过n个元素。
优先级:()>[]>\*
指针数组:是数组 int *p[n]
,存储指针的数组。数组名为p,数组长度为n。有n个指向int类型数据的指针。
int (*)[10] p2
; int (*)[10]
是指针类型,p2
是指针变量。
5.指针的几种情况
int* p[n]:
指针数组,一共n个元素,每个元素均为指向整型数据的指针.
int (*p)[n]
:数组指针,p为一个指针,指向一维数组,这个数组有n个整形数据。
int* p()
:指针函数,p指向函数的返回值。
int (*p)()
: 函数指针,p为指向函数的指针。
6.代码识别:
int * ( * (*fp1)(void *))[10]; //1
()优先级 (*fp1)
fp1为指针,指向一个函数。
(void *)
为指针函数,返回值也是指针,参数为void。fp1为指向指针函数的函数指针。
int* P[10] 数组,P函数返回值也是指针,指针数组。
综合:fp1 是指针指针函数的函数指针,并且函数指针的返回值是 长度为10的 指针数组。
7.结构和联合:
同一时刻,联合中值存放了一个被选中的成员,而结构的所有成员都存在。
对于联合的不同成员赋值,将会对其他成员进行重写,原来成员的值就不存在了,对于结构的不同成员赋值是不影响的。
8.对指针的理解
指针是一个变量,指向一块内存地址,指针的类型取决于指针指向的类型,其也可以访问其指向的内存地址。
9.缺省函数
默认构造函数 拷贝构造函数 析构函数 赋值函数
10.switch,c++不是安全的以及传递方式
switch()内的不能为浮点型,必须为整型或者枚举型。
C++不是安全的,因此两个不同类型的指针可以进行强制转换。
C++值的传递方式:值传递 指针传递 引用传递