C++ Primer笔记8_动态内存_智能指针

1.动态内存

C++中,动态内存管理是通过一对运算符完成的:new和delete。C语言中通过malloc与free函数来实现先动态内存的分配与释放。C++中new与delete的实现其实会调用malloc与free。

new分配:

分配变量空间:

int *a = new int; // 不初始化
int *b = new int(10); //初始化为10
string *str = new string(10, );

分配数组空间:

int *arr = new int[10];//分配的数组空间未初始化!

delete释放:

delete a;
delete [] arr;//delete的对象是数组

2.智能指针

由于 C++ 语言没有自动内存回收机制,每次 new 出来的内存都要手动 delete。程序员忘记 delete,流程太复杂,最终导致没有 delete,异常导致程序过早退出,没有执行 delete 的情况并不罕见。

用智能指针便可以有效缓解这类问题,本文主要讲解参见的智能指针的用法。包括:std::auto_ptr、boost::scoped_ptr、boost::shared_ptr、boost::scoped_array、boost::shared_array、boost::weak_ptr、boost::
intrusive_ptr。

C++11新标准提供了两种智能指针,负责自动释放所指向的对象。shared_ptr允许多个指针指向同一个对象;unique_ptr则"独占"所指向的对象。标准库还定义了一个名为weak_ptr的伴随类;这三种类型都定义在memory头文件中。

对于编译器来说,智能指针实际上是一个栈对象,并非指针类型,在栈对象生命期即将结束时,智能指针通过析构函数释放有它管理的堆内存。所有智能指针都重载了“operator->”操作符,直接返回对象的引用,用以操作对象。访问智能指针原来的方法则使用“.”操作符。

访问智能指针包含的裸指针则可以用 get() 函数。由于智能指针是一个对象,所以if (my_smart_object)永远为真,要判断智能指针的裸指针是否为空,需要这样判断:if (my_smart_object.get())。

智能指针包含了 reset() 方法,如果不传递参数(或者传递 NULL),则智能指针会释放当前管理的内存。如果传递一个对象,则智能指针会释放当前对象,来管理新传入的对象。

2.1 auto_ptr

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

class A
{
public:
	A(int n, string s):num(n), str(s)
	{
	}
	~A()
	{
		cout << "~A : " << num << " " << str  << endl;
	}
	void print()
	{
		cout << "num: " << num << ", str: " << str << endl;
	}
	void setNum(int n)
	{
		num = n;
	}
	void setString(string s)
	{
		str = s;
	}
private:
	int num;
	string str;
};

int main()
{
	auto_ptr<A> my(new A(10, string(10, 'n')));
	if(my.get())
	{
		my->print();
		(*my).setNum(20);
		my.get()->setString(string("SCOTT"));
		my->print();
	}
	auto_ptr<A> my1 = my;

	cout << my.get() << "------" << my1.get()<< endl;
	//my->print();	segment default!

	return 0;
}

运行结果:

num: 10, str: nnnnnnnnnn

num: 20, str: SCOTT

0------0x9cd2028 ——赋值后所有权转移到my1 ,原来的my相当于野指针!

~A : 20 SCOTT

上述程序最后如果加上

my.release();

my1.release();

则会发现析构函数不会被执行! 说明release函数不会释放对象。

总结:std::auto_ptr 可用来管理单个对象的对内存,但是,请注意如下几点:

(1)    尽量不要使用“operator=”。如果使用了,请不要再使用先前对象。

(2)    记住 release() 函数不会释放对象,仅仅归还所有权。

(3)    std::auto_ptr 最好不要当成参数传递(读者可以自行写代码确定为什么不能)。

(4)    由于 std::auto_ptr 的“operator=”问题,有其管理的对象不能放入 std::vector 等容器中。

由于 std::auto_ptr 引发了诸多问题,一些设计并不是非常符合 C++ 编程思想,所以引发了下面 boost 的智能指针,boost 智能指针可以解决如上问题。

2.2 boost::scoped_ptr

boost::scoped_ptr 属于 boost 库,定义在 namespace boost 中,包含头文件#include<boost/smart_ptr.hpp> 便可以使用。boost::scoped_ptr 跟 std::auto_ptr 一样,可以方便的管理单个堆内存对象,特别的是,boost::scoped_ptr 独享所有权,避免了 std::auto_ptr恼人的几个问题。

#include <iostream>
#include <boost/smart_ptr.hpp>
using namespace std;
using namespace boost;

class A
{
public:
	A(int n, string s):num(n), str(s)
	{
	}
	~A()
	{
		cout << "~A : " << num << " " << str  << endl;
	}
	void print()
	{
		cout << "num: " << num << ", str: " << str << endl;
	}
	void setNum(int n)
	{
		num = n;
	}
	void setString(string s)
	{
		str = s;
	}
private:
	int num;
	string str;
};

int main()
{
	scoped_ptr<A> my(new A(10, string(10, 'n')));
	if(my.get())
	{
		my->print();
		(*my).setNum(20);
		my.get()->setString(string("SCOTT"));
		my->print();
	}
//	scoped_ptr<A> my1 = my;	 error!  scoped_ptr 没有重载operator=,不会导致所有权转移  scoped_ptr也没有定义release函数
	cout << my.get() << "------" << my.get()<< endl;

	return 0;
}

2.3 boost::shared_ptr

boost::shared_ptr 属于 boost 库,定义在 namespace
boost 中,包含头文件#include<boost/smart_ptr.hpp> 便可以使用。在上面我们看到 boost::scoped_ptr 独享所有权,不允许赋值、拷贝,boost::shared_ptr 是专门用于共享所有权的,由于要共享所有权,其在内部使用了引用计数。boost::shared_ptr 也是用于管理单个堆内存对象的。

#include <iostream>
#include <boost/smart_ptr.hpp>
using namespace std;
using namespace boost;

class A
{
public:
	A(int n, string s):num(n), str(s)
	{
	}
	~A()
	{
		cout << "~A : " << num << " " << str  << endl;
	}
	void print()
	{
		cout << "num: " << num << ", str: " << str << endl;
	}
	void setNum(int n)
	{
		num = n;
	}
	void setString(string s)
	{
		str = s;
	}
private:
	int num;
	string str;
};

void test(shared_ptr<A> &test)
{
	test->print();
	return ;
}

int main()
{
	shared_ptr<A> my(new A(10, string(10, 'n')));
	if(my.get())
	{
		my->print();
		(*my).setNum(20);
		my.get()->setString(string("SCOTT"));
		my->print();
	}
	cout << "my.use_count: " << my.use_count() << endl;
	test(my);
	cout << "my.use_count: " << my.use_count() << endl;

//	cout << my.get() << "------" << my1.get()<< endl;
	//my->print();	segment default!

	return 0;
}

运行结果:

num: 10, str: nnnnnnnnnn

num: 20, str: SCOTT

my.use_count: 1

num: 20, str: SCOTT

my.use_count: 1

~A : 20 SCOTT

boost::shared_ptr 也可以很方便的使用。并且没有 release() 函数。关键的一点,boost::shared_ptr 内部维护了一个引用计数,由此可以支持复制、参数传递等。boost::shared_ptr 提供了一个函数 use_count() ,此函数返boost::shared_ptr 内部的引用计数。可以看到在test函数返回后,引用计数又降低为1;当我们需要使用一个共享对象的时候,boost::shared_ptr 是再好不过的。

2.4 weak_ptr

boost::weak_ptr 属于 boost 库,定义在 namespace boost 中,包含头文件#include<boost/smart_ptr.hpp> 便可以使用。

在讲 boost::weak_ptr 之前,让我们先回顾一下前面讲解的内容。似乎boost::scoped_ptr、boost::shared_ptr 这两个智能指针就可以解决所有单个对象内存的管理了,这儿还多出一个 boost::weak_ptr,是否还有某些情况我们没纳入考虑呢?

回答:有。首先 boost::weak_ptr 是专门为 boost::shared_ptr 而准备的。有时候,我们只关心能否使用对象,并不关心内部的引用计数。boost::weak_ptr 是 boost::shared_ptr 的观察者(Observer)对象,观察者意味着 boost::weak_ptr 只对 boost::shared_ptr 进行引用,而不改变其引用计数,当被观察的 boost::shared_ptr 失效后,相应的 boost::weak_ptr 也相应失效。

写到这,先告一段落,理论知识是参考网上的博文,然后自己实现一些demo加深理解。

C++ Primer笔记8_动态内存_智能指针,布布扣,bubuko.com

时间: 2024-10-01 04:34:53

C++ Primer笔记8_动态内存_智能指针的相关文章

【C++ Primer | 12】动态内存与智能指针

#ifndef MY_STRBLOB_H #define MY_STRBLOB_H #include<iostream> #include<vector> #include<memory> #include<initializer_list> using namespace std; class StrBlob { public: typedef vector<string>::size_type size_type; StrBlob(); St

C++primer第十二章读书笔记---动态内存与智能指针

    目前为止我们使用过的静态内存,栈内存和内存池,静态内存用来保存局部static对象.类static成员,以及定义在任何函数之外的成员.栈内存用来保存定义在函数内部的非static成员,分配在静态 内存或栈内存中的对象由编译器自动创建或销毁,对于栈对象仅在其定义的程序块运行时才有效,static对象在程序运行之前分配,程序结束时销毁.除了静态内存和栈内存外,每个程序还拥有一个内存池(堆)在堆上分配动态对象,当动态对象不再使用时,我们必须显示的销毁它.     (一).动态内存与智能指针  

【足迹C++primer】39、动态内存与智能指针(3)

动态内存与智能指针(3) /** * 功能:动态内存与智能指针 * 时间:2014年7月8日15:33:58 * 作者:cutter_point */ #include<iostream> #include<vector> #include<memory> #include<string> using namespace std; /** 智能指针和异常 */ void f() { shared_ptr<int> sp(new int(42));

【足迹C++primer】39、动态内存与智能指针(2)

动态内存与智能指针(2) 直接管理内存 void fun1() { //此new表达式在自由空间构造一个int型对象,并返回指向该对象的指针 int *pi1=new int; //pi指向一个动态分配.未初始化的无名对象 string *ps3=new string; //初始化为空string int *pi2=new int; //pi指向一个未初始化的int int *pi3=new int(1024); //pi指向的对象的值为1024 string *ps4=new string(1

C++笔记(12):动态内存和智能指针

动态内存和智能指针 动态内存: 1.针对堆里面存放的对象 2.使用new delete运算符 3.智能指针:shared_ptr(多个指针指向同一个对象);  unique_ptr(一个指针指向一个对象);     weak_ptr(弱引用,管理shared_ptr) 4.标准库函数:make_shared<int>()

动态内存1(动态内存与智能指针)

静态内存用来保存局部 static 对象.类 static 数据成员 以及任何定义在函数之外的变量.栈内存用来存储定义在函数内部的非 static 对象.分配在静态或栈内存中的对象由编译器自动创建和销毁.对于栈对象,仅在其定义的程序块运行时才存在:static 对象在使用之前分配,在程序结束时销毁. 除了静态内存和栈内存,每个程序还拥有一个内存池.这部分内存被称作自由空间或堆.程序用堆来存储动态分配的对象--即,那些在程序运行时分配的对象.动态对象的生存周期由程序来控制,即当动态对象不再使用时,

第十二章 动态内存与智能指针

动态内存与智能指针 [智能指针]头文件#include<memory>shared_ptr: 允许多个指针指向同一个对象unique_ptr: "独占"所指向的对象weak_ptr:伴随类,它是一种弱引用,指向shared_ptr所管理的对象. 原文地址:https://www.cnblogs.com/sunbines/p/8552298.html

动态内存——动态内存与智能指针

全局对象在程序启动时分配,在程序结束时销毁.对于局部自动对象,当我们进入其定义所在的程序块时被创建,在离开块时销毁.局部static对象在第一次使用前分配,在程序结束时销毁. 除了自动和static对象外,C++还支持动态分配对象.动态分配的对象的生命期与它们在哪里创建是无关的,只有当显示地被释放时,这些对象才会销毁. 静态内存用来保存局部static对象.类static数据成员以及定义在任何函数之外的变量.栈内存用来保存定义在函数内的非static对象.分配在静态或栈内存中的对象由编译器自动创

动态内存和智能指针

c++中动态内存的管理是通过一对运算符来完成的:new.在动态内存中为对象分配空间并返回一个指向该对象的指针,我们呢,可以选择对对象进行初始化,delete接受一个动态对象的指针,销毁该对象,并返回与之关联的内存. 动态内存的使用的不足: 1.保证在正que的时间释放内存是及其困难 2.有时我们会忘记释放内存,这样就导致内存泄漏 3.有时还存在引用内存的情况,但是我们已经释放了它,这样就导致非法内存的指针 这样就产生了智能指针(smart pointer)来动态管理内存,智能指针优点: 1.行为