c++基础复习(2)

复习点:一、c++中四种cast转化的区别  二、c++中指针和引用的区别  三、智能指针 四、函数指针和指针函数

一、c++中的四种cast转化

它们的使用方法都是类似:static_cast<int>(z)

1、const_cast(常量转化)

用于将const变量转化为非const。这里需要注意:如果一个变量被定义为const,通过const_cast转化函数转化后,这个值还是不能改变的。这里我们需要记住一句话:const_cast不是为了改变const变量的值而设计的,在函数参数的传递上const_cast的作用才显示出来。

void fun(int* n)
{
	cout << n << endl;
}
int main()
{
	const int n = 5;
	//fun(&n);类型不匹配
	fun(const_cast<int*>(&n));
	return 0;
}

2、static_cast(静态转化,不作安全性检查)

(1)用于基础类型之间的转换。

(2)把空指针转化成目标类型的空指针。

(3)把任何类型的表达式转化为void类型。

(4)用于类层次结构中基类和派生类的之间指针和引用的转化。

(5)用于多态向上转化(派生类转基类),如果向下(基类转派生类)转化可以转成功,但结果未知(因为派生类中可能会新增加其他成员,转化过去就会导致这一部分的数据不确定)。

//Test1为派生类,Test为基类
Test1 t1(4,2);
Test t = static_cast<Test1>(t1);

static_cast在转化失败后不会返回空,而是返回那个转换的未知的东西,这就存在一定的安全性。

3、dynamic_cast(动态转化)

dynamic_cast主要用于类层次中的基类和派生类之间的指针和引用的转化,在运行时会进行类型检查,因此可以保证向下转化的安全性。

它通过判断在执行到该语句的时候变量的运行时的类型和要转化的类型是否相同来判断是否能够进行向下转化。

4、reinterpret_cast(重新解释转化)

和它的名字一样,这个几乎什么都可以转,但会出问题。

二、c++中指针和引用的区别

1、指针有自己的空间,而引用只是一个别名,和被引用对象指向同一块空间。

2、指针的大小为4个字节,而引用的大小为被引用对象的大小。

3、指针可以被初始化为NULL,但引用必须时一个已有对象的应用,即不能为一个没有的对象起别名。

4、指针可以指向其他对象,但引用只能时一个对象的引用(当修改时,虽然不会报错时,但也不起作用),不能改变,即别名一旦起了就是自己的不能被别人拿走。

5、指针可以有多级,而引用只有一级。

6、指针有函数指针,而没有函数引用。

相同的是:无论是通过指针还是引用传递的参数,在函数中,对它们的修改都会引起原数据的修改。

三、智能指针(smart pointer)

对于内存的管理时一件非常麻烦的事件:(1)自己申请的空间忘记释放。(2)程序在空间释放之前结束。(3)多次释放会导致程序崩溃。如果使用的java,那你就不要考虑这些问题,因为java语言有一个非常显著的特点就时它的“垃圾回收机制”,这个机制很好的解决了内存管理的问题。但c++中并没有这个机制,所以这些问题都需要c++程序员自己管理。但管理又是一件非常麻烦的事情,所以就引出了“智能指针”这个概念。这个类似于java垃圾回收机制的智能指针,可以帮助c++程序员管理内存。智能指针的作用就是帮助程序员管理内存。这里需要明白一点:智能指针虽然被称为指针,但却是一个类,它并不是一个指针,只是行为像指针。

原理:智能指针是一个类,当超出的作用域时,类就会自动调用析构函数,析构函数会自动释放资源。

c++中一共有4个:shared_ptr、weak_ptr、unique_ptr、auto_ptr

(1)unique_ptr

其中auto_ptr已经被c++11中所废弃了。而unique_ptr则是用来替换auto_ptr,它实现了独占式或严格拥有的概念,保证了同一时间内只有一个智能指针可以指向该对象。它对于避免资源泄漏特别用(new创建对象后因为发生异常而忘记调用delete)。

(2)shared_ptr

和unique_ptr的独占不同的时,shaerd_ptr允许多个智能指针指向相同的对象。shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向一个相同的内存。每次使用内部的引用计数就加1,每析构一次,内部的引用计数就会减1,当引用计数减为0时,自动删除所指向的内存空间。shared_ptr内部的引用计数是线程安全的,但对象的读取需要加锁。

	Test *test = new Test(10);
	shared_ptr<Test> pTest1 = shared_ptr<Test>(test);
	//shared_ptr<Test> pTest2 = shared_ptr<Test>(test);//会导致释放内存释放两次,程序崩溃。
	shared_ptr<Test> pTest2 = pTest1;//unique_ptr是不允许的
	cout << pTest1->_x << endl;//重载了->运算符,智能指针可以访问对象的成员(行为像指针)
	cout << pTest1.use_count() << endl;
	cout << pTest2.use_count() << endl;

除了上面的用一个原始指针初始化多个shared_ptr导致程序崩溃之外的问题之外,shared_ptr还存在使用不当导致的内存泄漏问题。

上面介绍过shared_ptr的实现方式是使用了一种引用计数的方法,而这种方式就可能会导致引用计数无法减为0,从而导致内存无法释放。在使用shared_ptr时要避免循环调用。即两个对象相互使用一个shared_ptr成员变量指向对方,会造成引用计数失效,从而导致内存泄漏。

#include <iostream>
#include <memory>
using namespace std;
class Test;
class TestChlid;
class Test
{
public:
	shared_ptr<TestChlid> _chlidPtr;
	void setPtr(shared_ptr<TestChlid> chlidPtr)
	{
		_chlidPtr = chlidPtr;
	}
	int _x;
	Test(int x)
	{
		_x = x;
	}
};
class TestChlid :public Test
{
public:
	shared_ptr<Test> _parentPtr;
	void setPtr(shared_ptr<Test> parentPtr)
	{
		_parentPtr = parentPtr;
	}
	int _y;
	TestChlid(int x, int y)
		:Test(x)
	{
		_y = y;
	}
};
void fun()
{
	shared_ptr<Test> p = shared_ptr<Test>(new Test(1));
	shared_ptr<TestChlid> c = shared_ptr<TestChlid>(new TestChlid(1, 2));
	p->setPtr(c);
	cout << "P1:" << p.use_count() << endl;
	cout << "C1:" << c.use_count() << endl;
	c->setPtr(p);
	cout << "P2:" << p.use_count() << endl;
	cout << "C2:" << c.use_count() << endl;
}
int main()
{
        //当退出函数时,只是将p,c的引用计数减了1,两个类的析构函数没有被调用
        fun();
	return 0;
}

(3)weak_ptr

上面说了shared_ptr在循环引用时导致内存泄漏问题,而导致这个问题的原因时引用计数在程序结束时无法被减为0。那么这个问题该如何解决那?为了解决这个问题,c++引入了weak_ptr智能指针。

weak_ptr的引入就是为了配合shared_ptr的工作,指向一个shared_ptr管理的独享。它不具有普通的智能指针的功能,没有办法单独使用,没有重载*和->,它最大的作用就是协助shared_ptr的工作,像旁观者那样观测资源的使用。因为wead_ptr的使用并不会导致shared的应用计数增加或减少,所以将上述两个类中的shared_ptr 类型修改为weak_ptr,就可以解决循环引用导致的内存协调问题。

四、函数指针和指针函数

(1)函数指针

声明格式:函数返回值类型 (*函数指针名)(参数)

使用:函数指针名()或(*函数指针名)()

函数指针是指向函数的指针变量。函数指针本身是一个指针,该变量指向一个具体的函数。和普通的指针指向int、char的指针一样,这里的就是指针指向了函数。在这里需要明白:C语言在编译的时候,会为每一个函数分配一个入口地址,就和数据的首地址差不多,通过这个入口地址就可以调用这个函数。而函数指针就是记录了这个函数的地址,和平常的记录的整形变量的地址是一样的。

#include <iostream>
using namespace std;
int fun2()
{
	cout << "HelloFun2!" << endl;
	return 0;
}

int fun1(int (*fun2)())
{
	(*fun2)();//第二种使用方式
	cout << "HelloFun1!" << endl;
	return 0;
}
int main()
{
	int (*funPtr1)(int (*fun)());
	funPtr1 = fun1;
	int(*funPtr2)();
	funPtr2 = fun2;
	fun1(fun2);//第一种使用方式
	return 0;
}

(2)指针函数

指针函数就是返回值为指针的函数,普通返回其他类型的函数没有区别,就是返回是指针。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值