首页 > 编程语言 >C++ 智能指针

C++ 智能指针

时间:2023-08-20 16:47:05浏览次数:39  
标签:std C++ ptr 智能 shared include e0 指针

智能指针

使用智能指针需要引入 memory 头文件

unique_ptr

#include<iostream>
#include<string>
#include<memory>

class Entity {
public:
	Entity() {
		std::cout << "Created Entity!" << std::endl;
	}
	~Entity() {
		std::cout << "Destoryed Entity!" << std::endl;
	}
	void Print() {}
};

int main() {
	{
		// std::unique_ptr<Entity> entity(new Entity());
		// 下面是更安全的写法
		// (如果构造函数抛出异常,不会得到悬空指针造成内存泄漏)
		std::unique_ptr<Entity> entity = std::make_unique<Entity>();
		entity->Print();
	}
	return 0;
}

unique_ptr指针会在离开作用域的时候自动销毁,这就是一个智能指针。

但请注意,unique_ptr指针不能复制的。假如说e1复制了e0,当e0离开作用域被销毁时,e1就指向了一片被销毁的空间,就出问题了。事实上你也不能复制,编译器没法编译的。

如果真的想复制,就要使用到另一个智能指针了,往下看。

shared_ptr

shared_ptr和unique_ptr一样的,都是智能指针,不过shared_ptr可以复制。先说说他是怎么解决unique_ptr无法复制的问题的:引用次数法。

大部分情况下都是引用次数法,还是上面那个例子,e1复制了e0,此时有两个指针指向了一片空间,引用次数为2,当e0离开作用域被销毁了,让引用次数减1。没少一个引用就减1,当引用次数为0时才释放内存。

用法和unique_ptr很像,上代码:

#include<iostream>
#include<string>
#include<memory>

class Entity {
public:
	Entity() {
		std::cout << "Created Entity!" << std::endl;
	}
	~Entity() {
		std::cout << "Destoryed Entity!" << std::endl;
	}
	void Print() {}
};

int main() {
	{
		std::shared_ptr<Entity> e0;
		{
			std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();
			e0 = sharedEntity; // 可以复制
		} // 出了这个作用域,sharedEntity没了,但是还有e0,所以没析构
	}// 这里e0也没了,在这里调用了析构函数
	return 0;
}

weak_ptr

弱指针,可以和shared_ptr一起使用。当一个weak_ptr复制一个shared_ptr时,不会让shared_ptr的引用次数增加。他只在乎他要复制的那个指针是否有效,但是不去维持这个指针一直有效。上代码:

#include<iostream>
#include<string>
#include<memory>

class Entity {
public:
	Entity() {
		std::cout << "Created Entity!" << std::endl;
	}
	~Entity() {
		std::cout << "Destoryed Entity!" << std::endl;
	}
	void Print() {}
};

int main() {
	{
		std::weak_ptr<Entity> e0;
		{
			std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();
			e0 = sharedEntity; // 可以复制
		} // 出了这个作用域,sharedEntity没了,weak_ptr e0没有增加引用次数,所以这里就析构了
	}
	return 0;
}

标签:std,C++,ptr,智能,shared,include,e0,指针
From: https://www.cnblogs.com/orzmiku/p/17644219.html

相关文章

  • C++ 链接库
    C++中使用库分为两种,静态库和动态库。简单来说,静态库最后会被编译进二进制文件,动态库不会,需要二进制文件从外部载入。以下操作均在VisualStudio2022中进行,以32位GLFW为例子(glfw.org)。首先下载glfw32位的可执行程序。在解决方案目录创建一个Dependencies文件夹(名字无所谓),然后......
  • C++ 创建库并使用
    创建库并使用!>使用VisualStudio2022创建项目和解决方案首先创建一个空项目,这里叫Game,同时VisualStudio会帮你创建解决方案。这个项目是我们的应用程序。创建项目来存库!>以静态库为例、右键解决方案,添加新项目Engine。此时就有了两个项目,Game和Engine:打开E......
  • C++ 类
    类类是一种把数据和功能结合在一起的方法。使用class来定义一个类,像这样:classPlayer{//创建一个Player类intx=0,y=0;intspeed=1;};通过类创建一个对象(实例化),像这样:Playerplayer;成员变量可以使用点(.)来访问对象的属性。player.speed=2;但......
  • C++ 类和结构体内外的Static
    类和结构体外的Static这里的static指的是在类外的static,意味着你要声明的是static的符号,链接将只在内部。(换句话说作用域只在他所在的.cpp文件)。下面是几组例子来理解:例子1:main.cpp#include<iostream>usingnamespacestd;voidfun(){cout<<"fun()inmain.cpp"......
  • C++ 继承
    继承一个类可以继承另一个类,避免了代码复写。被继承的类被叫做基类,继承的类叫做派生类。(或者说是父类和子类)继承类型当一个类派生自基类,该基类可以被继承为public、protected或private几种类型。继承类型是通过上面讲解的访问修饰符access-specifier来指定的。我们几乎......
  • C++ 构造函数与析构函数
    构造函数和析构函数构造函数构造函数会在实例化对象的时候执行,可以在实例化时传入参数。构造函数没有返回值。不需要声明返回值。构造函数的函数名与类名保持一致。//classname:PlayerPlayer(intxa=0,intya=0){//构造函数,传入初始坐标进行初始化......
  • C++ 变量初始化总结
    堆空间,new操作初始化1、对于有自己写构造函数的类,不论类型名后面有没有括号()或者数组[],都用构造函数进行初始化,如果构造函数delete,则编译报错;2、如果没有构造函数,则不加括号的new只分配内存空间,不进行内存的初始化,3、而加了括号()的new会在分配内存的同时初始化为0。栈空间......
  • c++基础入门
    1.安装g++编译器是编译C++代码使用的编译器,不要使用gcc了。在用户目录中单独创建一个文件夹存放下载后的3个安装文件,然后进入到目录中执行下面命令cd文件夹sudodpkg-i*.deb本地安装sudoapt-getinstallg++在线安装2.C++的语言特点及优势cwithclass(类)cplusplus大型......
  • Java为什么不让用指针?
    指针是C和C++等语言中的一个强大工具,它们允许开发者直接访问内存地址,从而为高性能的系统级编程提供了可能性。然而,Java在设计时刻意避免了指针的使用。为什么?2.Java的设计哲学简单性和可读性:Java的设计目标之一是使语言更加简单和容易理解,从而降低错误的可能性。指针经常被认为是......
  • 【python】如何将枚举指针传递至dll接口中
    在Python中,可以使用 ctypes 模块来将枚举指针传递给DLL接口。以下是一个简单的示例代码,演示了如何在Python中使用 ctypes 将枚举指针传递给DLL接口:importctypes#定义枚举类型classMyEnum(ctypes.Structure):_fields_=[("value",ctypes.c_int)]#加载D......