1.static关键字的作用
- 全局静态变量:在全局变量前加上关键字static,就定义成一个全局静态变量。作用域:全局静态变量在声明它的文件之外是不可见的。
- 局部静态变量:在局部变量之前加上static,局部变量就变成局部静态变量。作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域结束。但是当局部静态变量离开作用域后,不会销毁,会一直在内存中,只不过不能再进行访问,直到该函数再次被调用,并且值不会变。
- 静态函数:在函数返回类型前加上static关键字,函数就变成静态函数,函数的定义和声明在默认情况下都是extern的,但静态函数只是在声明它的文件中可见,不能被其他文件所用。
函数的实现使用static修饰,这个函数只能在本cpp中使用,不会同其他cpp中的同名函数冲突。 - 类的静态成员:在类中,静态成员可以实现多个对象之间的数据共享,并且使用静态数据成员还不会破坏隐藏的原则,即保证了安全性。因此,静态成员是类的所有对象中共享的成员,而不是某个对象的成员。
- 类的静态函数:它属于类而不是属于对象,在静态成员函数的实现中不能直接引用类中说明的非静态成员,可以引用类中说明的静态成员。如果静态成员函数中要引用非静态成员时,可通过对象来引用(通过参数传递的方式得到对象名,然后再通过对象名引用)。
2.C++中的类型转换符
- const_cast:用于将const变量转换成非const
- static_cast:用于各种隐式转换,比如非const转const,void*转指针等,static_cast能用于多态向上转化,如果向下转能成功但是不安全,结果未知。
- dynamic_cast:用于动态类型转换。只能用不含有虚函数的类,用于类层次间的向上和向下转化,只能转指针或引用。向下转换时,如果是非法的 对于指针 返回NULL,对于引用抛异常。
向上转换:指的是子类向基类转换
向下转换:指的是基类向子类转换
它通过判断在执行到该语句的时候变量的运行是类型和要转换的类型是否相同来判断是否能够进行向下转换。 - reinterpret_cast:几乎什么都能转,比如int转指针,可能会出问题,尽量少用。
3.指针和引用的区别
- 指针有自己的一块空间,而引用只是一个别名
- 指针的大小是4,引用则是被引用对象的大小
- 指针可以被初始化为NULL,而引用必须被初始化且必须是一个已有对象的引用
- 作为参数传递时,指针需要被解引用才可以对对象进行操作,而直接对应用的修改都会改变引用所指向的对象
- 可以有const指针,但没有const引用
- 指针在使用中可以指向其他对象,但是引用只能是一个对象的引用,不能被改变
- 指针可以有多级指针(**p),而引用只有一级
- 指针和引用使用++运算符的意义不一样
- 如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄漏。
4.C++中的智能指针
C++里面有四个智能指针:auto_ptr、shared_ptr、weak_ptr、unique_ptr,其中后三个是C++11支持,第一个已经被C++11弃用。
为什么要使用智能指针?
智能指针的作用是管理一个指针,因为存在以下这种情况:申请的空间在函数结束时忘记释放,造成内存泄漏。使用智能指针可以避免这种问题,因为智能指针就是一个类,当超出这个类的作用域后,类会自动调用析构函数,析构函数自动释放资源。
- auto_ptr(C++98方案,C++11已经弃用)采用所有权模式。
auto_ptr<string> p1(new string("hello world"));
auto_ptr<string> p2;
p2 = p1; //auto_ptr不会报错
此时不会报错,p2剥夺了p1的所有权,但是当程序运行时访问p1将会报错。所以auto_ptr的缺点是:存在潜在的内存崩溃问题。
- unique_ptr: 替换auto_ptr,unique_ptr实现独占式拥有或严格拥有概念,保证同一时间内只有一个智能指针可以指向该对象。它对于避免资源泄漏特别有用。
unique_ptr<string> p3(new string("hello world"));
unique_ptr<string> p4;
p2 = p1; //unique_ptr会报错
编译器认为p4=p3非法,避免了p3不再指向有效数据的问题。因此unique_ptr比auto_ptr更安全。
-
shared_ptr:共享式拥有概念。多个智能指针可以指向相同对象,该对象和其相关资源会在“最后一个引用被销毁”的时候释放。从名字shared就可以看出了资源可以被多个指针共享。可以通过use_count()来查看资源的所有者个数。
-
weak_ptr: 是一中不控制对象生命周期的智能指针,它指向一个shared_ptr管理的对象,weak_ptr设计的目的是为了配合shared_ptr而引入的一种智能指针来协助它工作的,解决shared_ptr相互引用时的死锁问题。如果两个shared_ptr相互引用,那么这两个指针的引用计数永远不可能为0,资源不会释放。
5.数组与指针的区别
- 指针保存数据的地址,数据保存数据
- 指针间接访问数据,首先获得指针的内容,然后将其作为地址,从该地址中提取数据,而数组是直接访问数据
- 指针通常用于动态的数据结构,数组通常用于固定数目且数据类型相同的类型
- 指针通过malloc或new分配内存,free或delete释放内存,数组隐式分配和删除
- 指针通常指向匿名数据,操作匿名函数,数组自身即为数据名
6.野指针是什么
野指针就是指向一个已删除的对象或者未申请访问受限内存区域的指针。
7.为什么父类的构函数必须是虚函数,C++默认析构函数不是虚函数?
将可能会被继承的父类的析构函数设置为虚函数,可以保证在释放基类指针时可以释放掉子类的空间,防止内存泄漏。
C++默认的析构函数不是虚函数是因为虚函数需要额外的虚函数表和虚表指针,占用额外的内存。而对于不会被继承的类来说,其虚析构函数会浪费内存。所以默认的析构函数不是虚函数。
8.函数指针
- 定义:函数指针是指向函数的指针变量。函数指针本身是一个指针变量,该指针变量指向一个具体的函数。这正如用指针变量可以指向整型变量、字符型、数组一样,这里指向函数。
C在编译时,每个函数读由一个入口地址,该入口地址就是函数指针所指向的地址。有了该指针变量后,可用来调用其函数,就如同用指针变量可引用其他类型变量一样。 - 用途:调用函数和做函数的参数,比如回调函数。
- 示例:
char * fun(char *p){...} //函数fun
char * (*pf)(char *p){...} //函数指针pf
pf = fun; //函数指针指向函数fun
pf(p); //通过函数指针pf调用函数fun
9.静态函数和虚函数的区别
静态函数在编译的时候就已经确定运行时机,虚函数在运行的时候动态绑定。虚函数因为用了虚函数表机制,调用的时候会增加一次内存开销。
虚函数的实现:在有虚函数的类中,类的最开始部分是一个虚函数表的指针,这个指针指向一个虚函数表,表中存放了虚函数的地址,实际的虚函数在代码段中。当子类继承了父类会同时继承其虚函数表,子类在重写父类中的虚函数时,会更新虚函数表中的地址为重写的函数地址。使用虚函数,会增加访问开销,降低效率。
10.重载和覆盖区别
- 重载:两个函数名称相同,但是参数列表不同,返回类型没有要求,在同一作用域中。
- 重写:子类继承父类,父类中的函数是虚函数,在子类中重新定义了这个虚函数,并重写函数体。
11. ++i和i++的实现
++i的实现
int & int::operator++()
{
*this += 1;
return *this;
}
i++的实现
const int int::operator(int)
{
int oldValue = *this;
++(*this);
return oldValue;
}
12.写个函数在main函数执行前先运行
__attribute((constructor))void before()
{
printf("before main\n");
}
转载:https://blog.csdn.net/luoyayun361/article/details/105026257