【智能指针二】智能指针互转

这篇具有很好参考价值的文章主要介绍了【智能指针二】智能指针互转。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、简述

智能指针的转换和普通指针的转换是一样的,只是用到的转换函数中间多了一个pointer,

  • 比如普通指针用到的static_cast、dynamic_cast、const_cast和reinterpret_cast。
  • 智能指针用到的与之对应的转换函数为:static_pointer_cast、dynamic_pointer_cast、const_pointer_cast和reinterpret_pointer_cast。
  • 如果你看了智能指针的转换的实现方式,你会发现,他调用的函数也是普通指针的转换函数。
关键字 说明
static_cast 用于良性转换,一般不会导致意外发生,风险很低。
const_cast 用于 const 与非 const、volatile 与非 volatile 之间的转换。
reinterpret_cast 高度危险的转换,这种转换仅仅是对二进制位的重新解释,但是可以实现最灵活的 C++ 类型转换。
dynamic_cast 用于类型安全的向下转型。或者向上转。

C++ static_cast、dynamic_cast、const_cast和reinterpret_cast

二、static_pointer_cast:静态转换

  • 主要讲解下有继承关系的转换(基本类型的本文不涉及)
  • 即可以向上转换(同隐式转换),也可以向下转换
#include <iostream>
#include <memory>
#include<string>
using namespace std;

class Parent;
class Child;

class Parent
{
public:
	Parent() {}  //暂时不明白为何子类需要需要父类的这个默认的构造函数,在此记录,后续研究
	Parent(string name) {
		m_name = name;
	}
	~Parent() {
		cout << "~Parent()" << endl;
	}
public:
	virtual void func()
	{
		cout <<"m_name="<<m_name << ":i am a father." << endl<<endl;
	}
public:
	string m_name;;
};

class Child:public Parent
{
public:
	Child(string name)
	{
		m_name = name;
	}
	~Child() {
		cout << "~Child()" << endl;
	}
public:
	void func()
	{
		cout << "m_name=" << m_name << ":i am a son." << endl<<endl;
	}
public:
	string m_name;
};

int main()
{
	shared_ptr<Parent> father(new Parent("father"));
	shared_ptr<Child> son(new Child("son"));

	// 隐式转换
	shared_ptr<Parent> father1 = son;
	cout << "爸爸1说" << endl;
	father1->func();
	// 向上转
	shared_ptr<Parent> father2 = static_pointer_cast<Parent>(son);
	cout << "爸爸2说" << endl;
	father2->func();
	
	// 向下转
	shared_ptr<Child> son2 = static_pointer_cast<Child>(father);
	cout << "儿子2说" << endl;
	son2->func();
	return 0;
}

输出

static_pointer_cast,C++随笔,c++,算法,开发语言

三、dynamic_pointer_cast:动态转换

  • 主要讲解下有继承关系的转换(基本类型的本文不涉及)
  • 即可以向上转换(同隐式转换),
  • 也可以向下转换(可能成功也可能失败,同以下demo中的两个向下转换。和dynamic_cast一样。)如下,
    • 1.把new出的子类指针赋值给父类指针,把此父类指针转换为子类指针,此情况转换正常
    • 2.把new出的父类赋值给父类指针,把此父类指针转换为子类指针,此情况转换失败
  • 避免运行时检查的开销。
#include <iostream>
#include <memory>
#include<string>
using namespace std;

class Parent;
class Child;

class Parent
{
public:
	Parent() {}  //暂时不明白为何子类需要需要父类的这个默认的构造函数,在此记录,后续研究
	Parent(string name) {
		m_name = name;
	}
	~Parent() {
		cout << "~Parent()" << endl;
	}
public:
	virtual void func()
	{
		cout <<"m_name="<<m_name << ":i am a father." << endl<<endl;
	}
public:
	string m_name;;
};

class Child:public Parent
{
public:
	Child() {}
	Child(string name)
	{
		m_name = name;
	}
	~Child() {
		cout << "~Child()" << endl;
	}
public:
	void func()
	{
		cout << "m_name=" << m_name << ":i am a son." << endl<<endl;
	}
public:
	string m_name;
};


int main()
{
	shared_ptr<Parent> father(new Parent("father"));
	shared_ptr<Child> son(new Child("son"));

	// 隐式转换
	shared_ptr<Parent> father1 = son;
	cout << "爸爸1说" << endl;
	father1->func();

	// 向上转
	shared_ptr<Parent> father2 = dynamic_pointer_cast<Parent>(son);
	cout << "爸爸2说" << endl;
	father2->func();

	// 向下转
	shared_ptr<Child> son2 = dynamic_pointer_cast<Child>(father);
	cout << "儿子2说" << endl;
	if (son2)
		son2->func();
	else
		cout << "爸爸转儿子,son2 is null" << endl<<endl;

	// 向下转
	shared_ptr<Parent> father3(new Child("son"));
	shared_ptr<Child> son3 = dynamic_pointer_cast<Child>(father3);
	cout << "儿子3说" << endl;
	if (son3)
		son3->func();
	else
		cout << "爸爸转儿子,son3 is null" << endl << endl;

	return 0;
}

输出

static_pointer_cast,C++随笔,c++,算法,开发语言

dynamic_pointer_cast 找不到官方的参考资料,但是可以可以从官方的dymanic_cast资料类推出以上转换规则。参考来自我的上一篇博客,以及cppreference.com/dynamic_cast

四、const_pointer_cast:

  • 同const_cast作用一致,去掉const属性,变成可修改的。
  • 如本文的demo,son的类型是const int类型的智能指针,原本是无法修改的,但是使用const_pointer_cast转换为int,就可以修改了。
  • 网上很多关于const_pointer_cast的例子基本都是错误的,他们使用const_pointer_cast后,还修改原来的int指针,可以说是没有意义的,因为即使没有const_pointer_cast,原来的int指针也是可以修改的。比如https://cplusplus.com/reference/memory/const_pointer_cast/、https://learn.microsoft.com
#include <iostream>
#include <memory>
#include<string>
using namespace std;

int main()
{
	shared_ptr<int> father(new int(10));
	shared_ptr<const int> son(father);

	// 此种情况,son是不可以直接改变值的,
	cout << "儿子son的值" << endl;
	cout << *son<<endl<<endl;
	
	// 但是,const 的son,经过const_pointer_cast转换的son2就可以赋值了。
	shared_ptr<int> son2 = const_pointer_cast<int>(son);
	*son2 = 20;
	cout << "儿子son2赋值后" << endl;
	cout << *son2;

	return 0;
}

输出

static_pointer_cast,C++随笔,c++,算法,开发语言

五、reinterpret_pointer_cast:

  • c++17和c++20新增的,目前找不到官方的demo,

  • 具体同reinterpret_cast,区别在于此reinterpret_pointer_cast针对的是智能指针的转换。

  • reinterpret 是“重新解释”的意思,顾名思义,reinterpret_cast 这种转换仅仅是对二进制位的重新解释,不会借助已有的转换规则对数据进行调整,非常简单粗暴,所以风险很高。

  • reinterpret_cast 可以认为是 static_cast 的一种补充,一些 static_cast 不能完成的转换,就可以用 reinterpret_cast 来完成,例如两个具体类型指针之间的转换

  • 简单来说,其他不敢转的,reinterpret_pointer_cast敢转,但是需要遵循场景要求,否则就会出现问题,具体场景参考reinterpret_cast的用法吧,因并reinterpret_pointer_cast没有找到官方的资料和用法。

#include <iostream>
#include <memory>
#include<string>
using namespace std;

class Parent
{
public:
	Parent() {}  //暂时不明白为何子类需要需要父类的这个默认的构造函数,在此记录,后续研究
	Parent(string name) {
		m_name = name;
	}
	~Parent() {
		cout << "~Parent()" << endl;
	}
public:
	virtual void func()
	{
		cout << "m_name=" << m_name << ":i am a father." << endl << endl;
	}
public:
	string m_name;
	int m_age = 30;
};

int main()
{
	std::shared_ptr<std::int8_t[]> p(new std::int8_t[4]{ 1, 1, 1, 1 });
	std::shared_ptr<std::int32_t[]> q = std::reinterpret_pointer_cast<std::int32_t[]>(p);

	std::int32_t r = q[0];
	cout << r<<endl;

	shared_ptr<Parent> father(new Parent("father"));

	// 将 shared_ptr<Parent> 转换为 shared_ptr<int>
	shared_ptr<int> sq=reinterpret_pointer_cast<int>(father);
	cout<<*sq<<endl;


	shared_ptr<char> son(new char[]("father"));
	// 将 shared_ptr<char> 转换为 shared_ptr<int>
	shared_ptr<int> sq2 = reinterpret_pointer_cast<int>(son);
	cout << *sq2<<endl;

	return 0;
}

参考
C++ static_cast、dynamic_cast、const_cast和reinterpret_cast
【cmake实战十】c++从动态库(dll)导出类文章来源地址https://www.toymoban.com/news/detail-639800.html

到了这里,关于【智能指针二】智能指针互转的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • srand(static_cast<unsigned>(time(NULL)))

    srand(static_castunsigned(time(NULL))) 在 C++ 中是用来初始化随机数生成器的代码。 这段代码中, time(NULL) 返回系统当前时间距离 Epoch(Unix 时间的起始时间,通常是1970年1月1日 00:00:00 UTC)的秒数,用 NULL 表示不考虑时区的情况下获取当前时间。然后,将这个时间值传递给 srand 函数,

    2024年02月07日
    浏览(42)
  • C++面试八股文:static_cast了解一下?

    某日二师兄参加XXX科技公司的C++工程师开发岗位第20面: 面试官:C++中支持哪些类型转换? 二师兄:C++支持C风格的类型转换,并在C++11引入新的规范了类型转换。 二师兄:C++11引入四种新的类型转换,分别是 static_cast 、 dynamic_cast 、 const_cast 、和 reinterpret_cast 。 二师

    2024年02月09日
    浏览(35)
  • 【C++入门到精通】C++类型的转换 | static_cast | reinterpret_cast | const_cast | dynamic_cast [ C++入门 ]

    当我们在进行C++编程时,类型转换是一个非常常见的操作。而在C++中,我们有多种类型转换的方式可供选择。其中包括** static_cast 、 reinterpret_cast 、 const_cast 和 dynamic_cast **。这些类型转换操作符能够在不同的场景下帮助我们实现所需的类型转换。本文将详细介绍这些类型转换

    2024年02月22日
    浏览(39)
  • Golang-指针(pointer)

    指针:指向内存地址的变量,指针用来存储变量的内存地址 Go 语言定义变量必须声明数据类型,因为不同数据类型的数据占用不同的存储空间,导致内存地址分配大小各不相同,所有指针只能存放同一类型变量的内存地址。 指针分为两种:类型指针和切片指针 类型指针允许

    2023年04月26日
    浏览(45)
  • Go invalid memory address or nil pointer dereference错误 空指针问题

    Go 指针声明后赋值,出现 panic: runtime error: invalid memory address or nil pointer dereference,这种是内存地址错误。 首先我们要了解 指针,指针地址 在 Go 中 * 代表取指针地址中存的值, 代表取一个值的地址 对于指针,我们一定要明白指针储存的是一个值的地址,但本身这个指针也需

    2024年02月05日
    浏览(59)
  • C++野指针(Wild Pointers)是什么?如何避免?如何正确地使用new和delete?

    C++野指针(Wild Pointers)是什么?如何避免? C++野指针(Wild Pointers)指的是那些指向无效内存地址的指针。野指针通常是由于内存管理不当导致的,比如未初始化的指针、指向已释放内存的指针、越界访问导致的指针等。野指针是非常危险的,因为它们可能引发未定义行为,

    2024年02月20日
    浏览(38)
  • Linux文件描述符和文件指针互转

    本文研究的主要是Linux中文件描述符fd与文件指针FILE*互相转换的相关内容,具体介绍如下。 1.文件描述符fd的定义: 文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一

    2024年02月08日
    浏览(42)
  • 【让你从0到1学会C语言】指针/数组传参以及static关键字

    作者:喜欢猫咪的的程序员 专栏:《C语言》 喜欢的话:世间因为少年的挺身而出,而更加瑰丽。                                  ——《人民日报》 如果对 指针了解不多的话,请先看我的另外一篇博客: http://t.csdn.cn/0rd9D http://t.csdn.cn/0rd9D 二维数组传参: arr为二维数

    2024年02月16日
    浏览(44)
  • 写个简单的管理数组指针的智能指针

    模板智能数组指针 1.管理任意类型的数组指针 2.释放的时候自动删除数组指针指向的内存 3.通过指针计算数组中的个数   3.要有指针的样式和数组的样式 4.支持for范围查询和迭代器 5.实例用法  

    2024年02月08日
    浏览(51)
  • 【重学C++】02 脱离指针陷阱:深入浅出 C++ 智能指针

    【重学C++】02 脱离指针陷阱:深入浅出 C++ 智能指针 大家好,今天是【重学C++】系列的第二讲,我们来聊聊C++的智能指针。 在上一讲《01 C++如何进行内存资源管理》中,提到了对于堆上的内存资源,需要我们手动分配和释放。管理这些资源是个技术活,一不小心,就会导致内

    2024年02月05日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包