C++中的auto_ptr智能指针的作用及使用方法详解

2025-05-27 0 15

智能指针(auto_ptr) 这个名字听起来很酷是不是?其实auto_ptr 只是C++标准库提供的一个类模板,它与传统的new/delete控制内存相比有一定优势,但也有其局限。本文总结的8个问题足以涵盖auto_ptr的大部分内容。

auto_ptr是什么?

auto_ptrC++标准库提供的类模板,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同时被分给两个拥有者。当auto_ptr对象生命周期结束时,其析构函数会将auto_ptr对象拥有的动态内存自动释放。即使发生异常,通过异常的栈展开过程也能将动态内存释放。auto_ptr不支持new 数组。

该类型在头文件memory中,在程序的开通通过 #include<memory> 导入,接下来讲解该智能指针的作用和使用。

使用方法:

  auto_ptr<type> ptr(new type()); 这是该指针的定义形式,其中 type 是指针指向的类型,ptr 是该指针的名称。

  比如该type 是int,具体定义如下:

  auto_ptr<int> ptr(new int(4));

  比如该type 是map<int,vector<int> >,具体定义如下:

  auto_ptr<map<int,vector<int> > > ptr(new map<int,vector<int> > ());

  当然可以先定义,后赋值,如下所示:

  auto_ptr<map<int,int> > ptr;
  ptr = auto_ptr<map<int,int> >(new map<int,int> ());

作用1:保证一个对象在某个时间只能被一个该种类型的智能指针所指向,就是通常所说的对象所有权。

作用2:对指向的对象自动释放的作用,详情看如下代码。

代码片段一:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31
#include <iostream>

#include <string.h>

#include <memory>

#include <string>

#include <Windows.h>

#include <map>

#include <ctime>

#include <vector>

using namespace std;#define MAXN 20000000

class test_ptr

{

public:

map<int,int> *p;

test_ptr()

{

p = new map<int,int>();

for(int i = 0;i<MAXN;i++)

p->insert(make_pair(i,i));

}

};

int main(int argc,char *argv[])

{

for(int i = 0;i<100;i++)

{

Sleep(1000);

cout << i << endl; // 输出 创建次数

test_ptr * tmp = new test_ptr();

}

system("pause");

return 0;

}

在某些情况下,可能我们就会写出上面的代码来,通过运行会发现存在内存溢出。对于一些经验老道的程序员可能会作如下改写:

代码片段二:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37
#include <iostream>

#include <string.h>

#include <memory>

#include <string>

#include <Windows.h>

#include <map>

#include <ctime>

#include <vector>

using namespace std;

#define MAXN 20000000

class test_ptr

{

public:

map<int,int> *p;

test_ptr()

{

//p = auto_ptr<map<int,int> > (new map<int,int>());

p = new map<int,int>();

for(int i = 0;i<MAXN;i++)

p->insert(make_pair(i,i));

}

~test_ptr()

{

delete p;

}

};

int main(int argc,char *argv[])

{

for(int i = 0;i<100;i++)

{

Sleep(1000);

cout << i << endl;

test_ptr * tmp = new test_ptr();

}

system("pause");

return 0;

}

在test_ptr 类中的析构函数中添加内存释放代码,但是在main函数中,定义的局部指针,当局部指针失效时并不会自动调用析构函数,在这种情况下也会导致内存泄漏问题。当然,如果细心的程序员可以在 test_ptr * tmp = new test_ptr() 后面加上一句 delete tmp ,这样也能够释放内存,不会出现内存泄漏问题。但是在某些情况下,很容易漏写,为了解决此问题,auto_ptr 就能发挥作用了。

代码片段三:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36
#include <iostream>

#include <string.h>

#include <memory>

#include <string>

#include <Windows.h>

#include <map>

#include <ctime>

#include <vector>

using namespace std;

#define MAXN 20000000

class test_ptr

{

public:

map<int,int> *p;

test_ptr()

{

p = new map<int,int>();

for(int i = 0;i<MAXN;i++)

p->insert(make_pair(i,i));

}

~test_ptr()

{

delete p;

}

};

int main(int argc,char *argv[])

{

for(int i = 0;i<100;i++)

{

Sleep(1000);

cout << i << endl; //输出创建次数

auto_ptr<test_ptr> tmp = auto_ptr<test_ptr> (new test_ptr());

}

system("pause");

return 0;

}

在main函数中,创建test_ptr类型指针时,该指针是auto_ptr 类型的智能指针,当智能指针失效时,会自动调用该类的析构函数。所以这种写法可以不再显示调用delete 语句了。但是该智能指针也只是保证调用类的析构函数,如果析构函数并没有释放类中声明的变量,那该怎么办。

代码片段四:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40
#include <iostream>

#include <string.h>

#include <memory>

#include <string>

#include <Windows.h>

#include <map>

#include <ctime>

#include <vector>

using namespace std;

#define MAXN 20000000

class test_ptr

{

public:

//auto_ptr<map<int,int> > p;

map<int,int> *p;

test_ptr()

{

//p = auto_ptr<map<int,int> > (new map<int,int>());

p = new map<int,int>();

for(int i = 0;i<MAXN;i++)

p->insert(make_pair(i,i));

}

/*

~test_ptr()

{

delete p;

}

*/

};

int main(int argc,char *argv[])

{

for(int i = 0;i<100;i++)

{

Sleep(1000);

cout << i << endl; //输出创建次数

auto_ptr<test_ptr> tmp = auto_ptr<test_ptr> (new test_ptr());

}

system("pause");

return 0;

}

在这种情况下,还是会出现内存泄漏问题,为了解决该问题,对类中声明的指针也是需要声明为auto_ptr类型。

代码片段五:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32
#include <iostream>

#include <string.h>

#include <memory>

#include <string>

#include <Windows.h>

#include <map>

#include <ctime>

#include <vector>

using namespace std;

#define MAXN 20000000

class test_ptr

{

public:

auto_ptr<map<int,int> > p;

test_ptr()

{

p = auto_ptr<map<int,int> > (new map<int,int>());

for(int i = 0;i<MAXN;i++)

p->insert(make_pair(i,i));

}

};

int main(int argc,char *argv[])

{

for(int i = 0;i<100;i++)

{

Sleep(1000);

cout << i << endl; //输出创建次数

auto_ptr<test_ptr> tmp = auto_ptr<test_ptr> (new test_ptr());

}

system("pause");

return 0;

}

这样就不用显示定义类的析构函数,不用在外部显示调用delete函数,当然如果尽早调用delete函数也是可以的,尽早释放内存也比该指针失效再释放好一些,这些就是为了防止忘记调用。

通过如上分析:可以得出如下结论。

1 定义了智能指针,当智能指针失效时会自动调用类的析构函数。

2 在 类中定义的智能指针,不必在析构函数中显示的delete,当外部调用该类的析构函数时,会自动释放该智能指针指向的对象,释放内存。

3 如果类中定义的是智能指针,但是外部没有触发类中的析构函数调用,该智能指针指向的对象还是不能释放。

auto_ptr 智能指针的bug

auto_ptr 智能指针在c++ 11 标准中已经被抛弃,被抛弃的原因就是因为该bug。前面也提到过,一个对象只能被一个智能指针所引用,这样就会导致一个赋值问题。看如下代码

代码片段六:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28
#include <iostream>

#include <string.h>

#include <memory>

#include <set>

using namespace std;

#define MAXN 20000000

void pri(auto_ptr<set<int> > p)

{

set<int>::iterator ite = p->begin();

for(;ite!=p->end();ite++)

{

cout << *ite << endl;

}

}

int main(int argc,char *argv[])

{

auto_ptr<set<int> > ptr(new set<int> ());

for(int i = 0;i< 3;i++)

{

int a;

cin >> a;

ptr->insert(a);

}

pri(ptr);

pri(ptr);

system("pause");

return 0;

}

初看这代码没什么问题,不过运行程序会崩溃。这就是该智能指针最大的bug, 在程序32行 调用pri(ptr) ,程序到这并没什么问题,但是第二次调用pri(ptr) 时程序就会崩溃。原因就是前面讲过,一个对象智能被一个智能指针所指向,在第一次调用pri()函数时,为了保证这一原则,当把ptr指针传入pri函数时,程序内部就把ptr置为空,所以到第二次调用时,就会出现崩溃的情况。对于这种情况的解决之道就是使用shared_ptr 指针(该指针的原理是通过引用计数器来实现的)。

如果要使用shared_ptr 智能指针,需要安装boost库,该库还包括许多其他功能。有兴趣的可以尝试以下,该类中的智能指针还是比较好用。也不存在很多其他bug。

以上所述是小编给大家介绍的C++中的auto_ptr智能指针实例详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对快网idc网站的支持!

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 C++中的auto_ptr智能指针的作用及使用方法详解 https://www.kuaiidc.com/74812.html

相关文章

发表评论
暂无评论