1.引用
1.1引用的使用
1.引用在实践中主要是引用传参和引用做返回值中减少拷贝提高效率和改变引用对象时同时改变被引用对象
2.引用传参跟指针传参功能是类似的,引用传参相对更方便一些
3.引用和指针在实践中相辅相成,功能有重叠性,各有特点
在函数返回值类型的后面加&,即返回的是引用,实体是返回的值,那么在main函数里本来栈顶的数据是1,通过把4赋值给栈顶,则栈顶的数据就变为4而不是1,因为别名就是跟栈顶的数据是一样的,有相同的地址,改变一个都会改变,若不加&则返回的是一个临时变量,就是拷贝了一个与返回值一样的大小的数据,而赋值4给临时变量就会出错,临时变量生命周期用完就没了,当别名的实体是临时变量时,要加const,而这样临时变量的生命周期就会改变,当别名销毁时,这个临时变量就会销毁。
int& STTop(ST& rs)
{assert(rs.top > 0);return rs.a[rs.top-1];
}int main()
{调用全局的ST st1;STInit(st1);STPush(st1, 1);STPush(st1, 2);STModityTop(st1, 3);STTop(st1) = 4;}
表达式的返回值一个临时变量,具有常性,生命周期会被const影响,就是当别名是const,这个临时变量就不会马上销毁,当引用的销毁了这个临时变量才销毁
1.2const引用
1.可以引用一个const对象,但是必须用const引用。const也可以引用普通对象,因为对象的访问权限可以在引用的过程缩小,但是不能放大。
2.int& rb=a*3;double d=12.34;int& rd=d;a*3是一个表达式,是存储在一个临时变量中,就是说rb的引用对象是临时对象,而c++规定临时对象具有常性,所以这里触发了权限放大(常性是常量的特性,不能被修改,而引用没有const,就说明引用可以改变这个常量,权限被放大了),必须要用常引用才可以。(权限不可以放大,但是可以缩小,int b=1;const int& rb=b;)
3.临时对象就是编译器需要一个空间暂存表达式的求值结果时临时创建的一个未命名的对象,c++中把这个未命名对象叫做临时对象
4.在类似转换时会发生隐式转换,有临时变量,例如int a=10 是常量10拷贝放到整形变量a里面,函数返回值也会有临时变量
2.内联函数
1.用inline修饰的函数叫做内联函数,编译时c++编译器会在调用的地方展开内联函数,调用内联函数就不需要建立栈帧了,可以提高效率。
#define Add(a,b) ((a)+(b))
int main()
{int ret = Add(1, 2);//宏定义后面不加分号是因为下面有报错//cout << Add(1, 2); << endl;//之所以要加外面的括号是防止优先级导致结果错cout << Add(1, 2) * 5 << endl;//之所以里面加括号也是优先级会影响Add(1 & 2, 3 & 4);return 0;
}
2.inline对于编译器而言只是一个建议,你加了inline编译器也可以选择在调用的地方不展开,不同编译器关于inline什么情况是不同的(代码的行数),c++为规定这个。inline适用于频繁调用的短小函数,对于递归函数,代码多一点的函数,加上inline也会被编译器忽略掉。
3.C语言实现宏宏函数也会在预处理时替换展开,但是宏函数实现很复杂且容易出错,不方便调试,C++设计inline目的是替换C的宏函数
4.vs编译器debug版本下默认是不展开inline的,这样方便调试,debug版本想展开需要设置一下
5.inline不建议声明和定义分离到俩个文件,分离会导致链接错误。因为inline被展开,就没有函数地址,链接时会报错。
3.指针空值nullptr
在C语言中NULL实际上是一个宏,在传统的C头文件(stddef.h)里,可以看到下面的代码:
#ifndef NULL#ifdef __cplusplus#define NULL 0#else#define NULL ((void *)0)#endif#endif
NULL可能被定义为字面常量0,或者定义为无类型指针(void*)的常量。下面是使用NULL遇到的麻烦,比如:
void Fun(int x)
{cout << "f(int)" << endl;
}
void Fun(int* x)
{cout << "f(int *)" << endl;
}
int main()
{Fun(0);Fun(NULL);//Fun((void*)0);return 0;
}
可以看到俩个都是int,NULL为参数并没有打印int*,而(void*)0就会报错,因为俩个参数都不符合,要隐式转换,不知道进哪一个函数里面,所以NULL设计的有些不合理,于是有了nullptr,
C++11中引入nullptr,nullptr是一种特殊关键字,nullptr是一种特殊类型的字面量,它可以转换成任意其它类型的指针类型。使用nullptr定义指针可以避免类型转换的问题,因为nullptr只能被隐式转换成指针类型,而不能转换为整数类型。
4.类
4.1类的引入
C语言结构体只能定义变量,在C++中,结构体不仅可以定义变量,也可以定义函数。
C语言用的是struct,而C++用class来代替,也可以使用struct。
4.2类的定义
class className{// 类体:由成员函数和成员变量组成}; // 一定要注意后面的分号
class为定义类的关键字,className为类的名字,{}为类的主体,注意类定义结束时后面的分号不能省略。
类体中内容为类的成员:类中的变量为类的属性或成员变量;类中的函数称为类的方法或者成员函数。
类的俩种定义方式:
1.声明和定义全部放在类体中,注意的是在类中定义的成员函数会被当做内联函数处理
下面定义一个类:
class person
{
public:void ShowInfo(){cout << _name << _sex << _age << endl;}
private:char* _name;char* _sex;int _age;
};int main()
{return 0;
}
也可以把成员函数的实现放在另一个文件里面。
4.3类的访问限定符及封装
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
访问限定符说明:
1.public修饰的成员在类外可以被访问
2.protected和private修饰的成员在类外不能直接被访问
3.访问权限作用域从该访问限定符出现的位置开始到下一个访问限定符出现时为止
4.如果后面没有访问限定符,作用域到}结束
5.private默认权限为private,struct默认为public
4.4类的实例化
用类类型创建对象的过程,称为类的实例化
1.类是对象进行描述的,是一个模型一样的,限定了类有那些成员,定义出一个类并没有分配实际的内存空间来存储它
2.一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,并存储类成员变量