语言基础(一)
1.Static关键字的作用
(1)全局静态变量:在全局变量前面加static ,全局变量就变成全局静态变量
存储:全局静态变量被存储在静态存储区域,在整个运行期间一直存在。
初始化:未被初始化的全局静态变量会被自动初始化位0(自动对象的值是任意的,除非他被显示初始化)
作用域:全局静态变量在声明他的文件之外是不可见的,准确的说是在定义之处开始,到文件结尾。
自动化??
(2)局部静态变量:在局部变量之前加上static,局部变量就成为一个局部静态变量。
存储:静态存储区域
初始化:未别初始化的 全局静态变量会被自动初始化为0,(自动对象的值是任意的,除非被显示初始化)
作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域结束。但是当局部静态变量离开作用域后,并没有销毁,而是仍然存储在静态存储区中,只不过我们不能再对他进行访问,知道该函数再次被调用,并且值不变。
(3)静态函数:在函数函数返回类型前面加static,函数就定义为静态函数,函数的定义和声明在默认情况下都是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。
函数的实现用static修饰,那么这个函数只在本文件内使用,不会同其他的文件中的同名函数引起冲突。
warning:如果要在多个cpp内复用该函数,就要把它的声明提到头文件中去,否则cpp内声明要加static。
(4)类的静态成员
在类中,静态成员可以实现多个对象之间数据的共享,并且使用静态成员还不会破坏隐藏的原则。对多个对象来说,静态数据成员只存储在一处,供所有对象使用
(5)类的静态函数:
在类中,静态成员函数和静态成员数据一样,他们都属于类的静态成员,他们都不是对象成员,因此,对静态成员的引用都不需要对象名。
在静态成员函数的实现中,不能直接引用类中声明的非静态成员。如果静态成员函数要引用非静态成员需要通过对象来引用。
2.C++和C的区别
设计思想上:
C++是面向对象的语言,而C是面向过程的结构化编程语言
语法上:
C++具有封装,继承和多态三种特性
C++相比C增加了许多类型安全的功能,比如强制类型转换。
C++支持范式编程,比如模板类,模板函数等
3.说一下C++中static关键字的作用
1.改变链接属性:当同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。如果加了static,就会对其它源文件隐藏。
2.改变存储类型:在代码块内声明,static 修改标识符的存储类型,由自动变量改为静态变量,这种变量在程序执行之前就创建,在程序执行的整个周期都存在。
4.C++中四中cast转换
四中转换:static_cast,dynamic_cast,const_cast,reinterpret_cast
1.const_cast:用于将const转为非const
2.static_cast: 用于各种隐式转换,比如将非const转const,void*转指针等,但是static_cast能用于多态向上转化,如果向下转化能成功,但是不安全,结果未知。
3.dynamic_cast: 用于动态类型转化。只能用于含有虚函数的类,用于类层次见的向上和向下转化。只能转指针或引用。向下转化时,如果是非法的对于指针返回NULL,对于引用抛异常
4.reinterpret_cast:几乎都可以转,比如将int转指针,可能会出问题,用的比较少。
5.为什么不用C的强制类型转化?
C的转化不够明确,而且不能进行错误检查,容易出错。
6.C/C++中指针和引用的区别?
引用是某一变量的别名,对引用的操作与对变量的操作完全一样。
指针存放着变量的地址,通过指针可以找到变量在内存中的存储位置。
(1).指针有自己的一块内存空间,而引用只是一个别名。
(2).使用sizeof看一个指针的大小是4,而引用则是被引用对象的大小。
(3).指针可以被初始化未NULL,而引用必须被初始化切必须是一个已有对象的引用。
(4).作为参数传递时,指针需要被解引用才可以对对象进行操作,而直接对引用的修改都会改变引用所指向的对象。
(5).可以有const指针,但是没有const引用。
(6).指针在使用的时候可以指向其他对象,但是引用只能是一个对象的引用,不能被改变。
(7).指针可以有多级指针,而引用只有一级
7.智能指针:shared_ptr,unique_ptr,weak_ptr,auto_ptr
(1) auto_ptr已经被C++11抛弃
(2) 为什么使用智能指针:智能指针的作用是管理一个指针,因为存在以下这种情况:申请的空间在函数结束时忘记释放,造成内存泄露。使用智能指针能很大程度避免这个问题,因为智能指针就是一个类,当超出了类的作用域时,类会自动调用析构函数,析构函数会自动释放内存空间,不需要手动释放内存空间。
(3) unique_ptr:实现独占式拥有或严格拥有概念,保证同一时间只有一个智能指针可以指向该对象。它对于避免资源泄露(例如,以new创建对象后因为发生异常而忘记delete")特别有用。
unique_ptr<string> p1(new string("hello world"));
unique_ptr<string> p2;
p2= p1;//not allowed
当试图将一个unique_ptr赋值给另一个时,如果源unique_ptr是个临时右值,编译器允许这么做,如果源unique_ptr将存在一段时间,编译器将禁止这么做
unique_ptr<string> p3(new string("he");
unique_ptr<string> p4;
p4= p3; //not allow
p4 = unique_ptr<string>(new string("you"));
如果要将一个unique_ptr赋值给另一个可以使用std::move();
unique_ptr<string> ps1(new string("hello"));
unique_ptr<string> ps2;
ps2=move(ps1);
ps1=unique_ptr<string> (new string("ooo"));
(4)shared_ptr:shared_ptr实现共享式拥有。多个智能指针可以指向相同的对象,该对象和其他先关资源会在最后一个引用被销毁时候释放。shared_ptr使用计数机制来表明资源可以被几个指针共享。可以通过成员函数use_count()来查看资源的所有个数。除了可以用new来构造,还可以通过传入auto_ptr,unique_ptr,weak_ptr来构造。当我们release()时候,当前指针会释放资源所有权,计数减一。当计数等于0时,资源会被释放。
成员函数:use_count() 返回引用计数的个数
unique 返回是否独占
swap() 交换两个shared_ptr对象
reset() 放弃内部对象的所有权或拥有对象的变更,会引起原有对象的引用计数的减少
get() 返回内部对象指针
(5) weak_ptr
weak_ptr是一种不控制对象生命周期的智能指针,他指向一个shared_ptr管理的对象。weak_ptr只是提供了对管理对象一个访问手段。
weak_ptr设计的目的是为配合shared_ptr而引入的一种智能指针来协助shared_ptr工作,他只可以从shared_ptr或者另一个weak_ptr对象构造,他的构造和析构不会引起计数的增加和减少。weak_ptr是用来解决shared_ptr相互引用时引起的死锁问题,如果说两个shared_ptr相互引用,那么这两个指针的引用计数永远不会为0,资源永远不会被释放。
8.请回答一下野指针
指向一个非法的或已销毁的内存的指针。
为了避免此类野指针的出现,指针变量在创建的同时应该被初始化,要么将它设置为NULL,要么让它指向合法的内存
指针p被free或者delete之后,只是把指针所指的内存释放掉了,没有改变指针的值,此时,p沦落为野指针
解决此类野指针问题,我们应该当指针指向的内存被释放时,我们也应该将指针置空
9.空指针
空类型就是void,自然,空类型指针就是void *
void *可以指向任何类型对象的地址,表示这是一个指针,和地址值有关,但不知道存储在此地址上的对象的类型,所以在取空类型指针所指向的值的时候,应将空类型指针转换为对应的指针类型
1)空指针支持的操作
a. 与另一个指针比较
b. 向函数传递void *指针
c. 在函数里返回void *指针
d. 给另一个void *指针赋值
2)空指针不支持的操作
a. 不支持解引用,不能获取指向对象的值
b. 不能进行指针运算,比如移位操作
10.请介绍一下C++中的智能指针?
智能指针主要用于管理在堆上分配的内存,他将普通的指针封装位一个栈对象。当栈对象生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄露。C++11中最常用的智能指针类型为shared_ptr,他采用引用计数的方法,记录当前内存资源被多少个智能指针引用。该引用计数的内存在堆分配。当新增一个时引用计数加1,当过期时减一,只有引用计数未0时,智能指针才会自动释放引用的内存资源。可以通过make_shared或者构造函数传入普通指针,并可以通过get函数获得普通指针。
11.请回答一下:智能指针有没有内存泄露的情况?
当两个对象相互使用一个shared_ptr成员变量指向对方时会造成循环引用,使引用计数失效,从而导致内存泄露。
12.如何解决智能指针的内存泄露?
为了解决循环引用导致的内存泄露,引入了weak_ptr弱智针,weak_ptr的构造函数不会修改引用计数的值,从而不会对对象的内存进行管理,其类似一个普通指针,但是它不会指向引用计数的共享内存,但是可以检测到所管理的对象是否已经释放,从而避免非法访问。