memory动态内存管理学习之unique_ptr

此头文件是动态内存管理库的一部分。std::unique_ptr 是一种智能指针,它通过指针持有并管理另一对象,并在 unique_ptr 离开作用域时释放该对象。在发生下列两者之一时,用关联的删除器释放对象:

  • 管理它的 unique_ptr 对象被销毁。
  • 通过 operator=reset() 赋值另一指针给管理它的 unique_ptr 对象。

成员函数

(构造函数)

构造新的 unique_ptr
(公开成员函数)

(析构函数)

析构所管理的对象,如果存在的话
(公开成员函数)

operator=

unique_ptr 赋值
(公开成员函数)
修改器

release

返回一个指向被管理对象的指针,并释放所有权
(公开成员函数)

reset

替换被管理对象
(公开成员函数)

swap

交换被管理对象
(公开成员函数)
观察器

get

返回指向被管理对象的指针
(公开成员函数)

get_deleter

返回用于析构被管理对象的删除器
(公开成员函数)

operator bool

检查是否有关联的被管理对象
(公开成员函数)
单对象版本,unique_ptr<T>

operator*operator->

解引用指向被管理对象的指针
(公开成员函数)
数组版本,unique_ptr<T[]>

operator[]

提供到被管理数组的有索引访问
(公开成员函数)

代码示例:

#include <iostream>
#include <memory>

// unique_ptr deleter with state
class state_deleter {
	int count_;
public:
	state_deleter()
		:count_(0) {}
	template<class T>
	void operator()(T* p) {
		std::cout << "[deleted #" << ++count_ << "]\n";
		delete p;
	}
};

struct C{
	int a;
	int b;
};

int main()
{
	// unique_ptr constructor example
	std::default_delete<int> d;
	std::unique_ptr<int> u1;
	std::unique_ptr<int> u2(nullptr);
	std::unique_ptr<int> u3(new int);
	std::unique_ptr<int> u4(new int, d);
	std::unique_ptr<int> u5(new int, std::default_delete<int>());
	std::unique_ptr<int> u6(std::move(u5));
	std::unique_ptr<int> u7(std::move(u6));
	std::unique_ptr<int> u8(std::auto_ptr<int>(new int));

	std::cout << "u1: " << (u1 ? "not null" : "null") << '\n';
	std::cout << "u2: " << (u2 ? "not null" : "null") << '\n';
	std::cout << "u3: " << (u3 ? "not null" : "null") << '\n';
	std::cout << "u4: " << (u4 ? "not null" : "null") << '\n';
	std::cout << "u5: " << (u5 ? "not null" : "null") << '\n';
	std::cout << "u6: " << (u6 ? "not null" : "null") << '\n';
	std::cout << "u7: " << (u7 ? "not null" : "null") << '\n';
	std::cout << "u8: " << (u8 ? "not null" : "null") << '\n';

	// unique_ptr destructor example
	auto deleter = [](int *p) {
		delete p;
		std::cout << "deleter called\n";
	};
	std::unique_ptr<int, decltype(deleter)> foo(new int, deleter);
	std::cout << "foo " << (foo ? "is not" : "is") << " empty\n";

	// unique_ptr::operator= example
	std::unique_ptr<int> foo2;
	std::unique_ptr<int> bar2{ nullptr };
	foo2 = std::unique_ptr<int>(new int(101));  // rvalue
	bar2 = std::move(foo2);                       // using std::move

	std::cout << "foo2: ";
	if (foo2)
		std::cout << *foo2 << '\n';
	else
		std::cout << "empty\n";

	std::cout << "bar2: ";
	if (bar2)
		std::cout << *bar2 << '\n';
	else
		std::cout << "empty\n";

	// unique_ptr::get vs unique_ptr::release
											//foo3	bar3	p3
	std::unique_ptr<int> foo3;				//null
	std::unique_ptr<int> bar3;				//null	null
	int *p3 = nullptr;						//null	null	null
	std::cout << "foo3: ";
	if(foo3) std::cout << *foo3 << '\n';
	else std::cout << "(null)\n";

	std::cout << "bar3: ";
	if(bar3) std::cout << *bar3 << '\n';
	else std::cout << "(null)\n";

	std::cout << "p3: ";
	if(p3) std::cout << *p3 << '\n';
	else std::cout << "(null)\n";
	std::cout << '\n';

	foo3 = std::unique_ptr<int>(new int(10));	//(10)	null	null
	bar3 = std::move(foo3);						//null  (10)	null
	p3 = bar3.get();							//null	(10)	(10)
	*p3 = 20;									//null	(20)	(20)
	p3 = nullptr;								//null	(20)	null
	std::cout << "foo3: ";
	if (foo3) std::cout << *foo3 << '\n';
	else std::cout << "(null)\n";

	std::cout << "bar3: ";
	if (bar3) std::cout << *bar3 << '\n';
	else std::cout << "(null)\n";

	std::cout << "p3: ";
	if (p3) std::cout << *p3 << '\n';
	else std::cout << "(null)\n";
	std::cout << '\n';

	foo3 = std::unique_ptr<int>(new int(30));	//(30)	(20)	null
	p3 = foo3.release();						//null	(20)	(30)
	*p3 = 40;									//null	(20)	(40)
	std::cout << "foo3: ";
	if (foo3) std::cout << *foo3 << '\n';
	else std::cout << "(null)\n";

	std::cout << "bar3: ";
	if (bar3) std::cout << *bar3 << '\n';
	else std::cout << "(null)\n";

	std::cout << "p3: ";
	if (p3) std::cout << *p3 << '\n';
	else std::cout << "(null)\n";
	std::cout << '\n';

	delete p3;   

	// unique_ptr::get_deleter example
	state_deleter del;
	std::unique_ptr<int> p; //使用默认的deleter;
	// alpha and beta use independent copies of the deleter:
	std::unique_ptr<int, state_deleter> alpha(new int);
	std::unique_ptr<int, state_deleter> beta(new int, alpha.get_deleter());
	// gamma and delta share the deleter "del" (deleter type is a reference!):
	std::unique_ptr<int, state_deleter&> gamma(new int, del);
	std::unique_ptr<int, state_deleter&> delta(new int, gamma.get_deleter());
	
	std::cout << "resetting alpha...";	alpha.reset(new int);
	std::cout << "resetting beta...";	beta.reset(new int);
	std::cout << "resetting gamma...";	gamma.reset(new int);
	std::cout << "resetting delta...";	delta.reset(new int);

	std::cout << "calling gamma/delta deleter...\n";
	gamma.get_deleter() = state_deleter();//新的deleter
	// additional deletions when unique_ptr objects reach out of scope (in inverse order of declaration)

	// example of unique_ptr::operator bool
	std::unique_ptr<int> foo4;
	std::unique_ptr<int> bar4(new int(12));
	if(foo4) std::cout << "foo4 points to " << *foo4 << '\n';
	else std::cout << "foo4 is empty\n";

	if(bar4) std::cout << "bar4 points to " << *bar4 << '\n';
	else std::cout << "bar4 is empty\n";

	// unique_ptr::swap example
	std::unique_ptr<int> foo5(new int(10));
	std::unique_ptr<int> bar5(new int(20));
	std::cout << "foo5:" << *foo5 << '\n';
	std::cout << "bar5:" << *bar5 << '\n';
	foo5.swap(bar5);
	std::cout << "foo5:" << *foo5 << '\n';
	std::cout << "bar5:" << *bar5 << '\n';

	// unique_ptr::operator*
	std::unique_ptr<int> foo6(new int);
	std::unique_ptr<int> bar6(new int(100));
	std::cout << "foo6: " << *foo6 << '\n';
	std::cout << "bar6: " << *bar6 << '\n';
	*foo6 = *bar6 * 2;
	std::cout << "foo6: " << *foo6 << '\n';
	std::cout << "bar6: " << *bar6 << '\n';

	// unique_ptr::operator->
	std::unique_ptr<C> foo7(new C);
	std::unique_ptr<C> bar7;
	foo7->a = 10;
	foo7->b = 20;
	bar7 = std::move(foo7);
	if (foo7) std::cout << "foo7: " << foo7->a << ' ' << foo7->b << '\n';
	if (bar7) std::cout << "bar7: " << bar7->a << ' ' << bar7->b << '\n';

	// unique_ptr::operator[]
	std::unique_ptr<int[]> foo8(new int[5]);

	for (int i = 0; i < 5; ++i) 
		foo8[i] = i;

	for (int i = 0; i < 5; ++i)
		std::cout << foo8[i] << ' ';
	std::cout << '\n';

    return 0;
}


运行效果:

参考:

https://cplusplus.com/reference/memory/

https://zh.cppreference.com/w/cpp/header/memory

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
std::unique_ptr是C++11引入的智能指针,用于管理动态内存的生命周期。它提供了一种安全且方便的方式来分配和释放动态内存,避免了手动管理内存的繁琐和容易出错的问题。 要使用std::unique_ptr来开辟动态内存,可以按照以下步骤进行: 1. 包含头文件:首先需要包含<memory>头文件,因为std::unique_ptr是在该头文件中定义的。 2. 创建std::unique_ptr对象:使用std::unique_ptr来管理动态内存,需要创建一个std::unique_ptr对象,并将其初始化为指向动态内存的指针。例如: ```cpp std::unique_ptr<int> ptr(new int); ``` 这里创建了一个std::unique_ptr对象ptr,并将其初始化为指向一个int类型的动态内存。 3. 使用std::unique_ptr对象:可以像使用原始指针一样使用std::unique_ptr对象。例如,可以通过解引用操作符*来访问动态内存中的值,也可以使用箭头操作符->来访问动态内存中的成员。例如: ```cpp *ptr = 10; std::cout << *ptr << std::endl; ``` 这里将动态内存中的值设置为10,并输出该值。 4. 自动释放内存:当std::unique_ptr对象超出其作用域时,会自动释放所管理的动态内存。这意味着不需要手动调用delete来释放内存,从而避免了内存泄漏和悬空指针的问题。 总结一下,使用std::unique_ptr开辟动态内存的步骤是:包含头文件、创建std::unique_ptr对象并初始化为指向动态内存的指针、使用std::unique_ptr对象操作动态内存、自动释放内存。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值