c++ STL(標準程序庫) auto_ptr

前言:

c++ stl 標準程序庫提供了一種智能指針,幫助程序員防止"被異常拋出時發生資源泄露"
本篇只講述 auto_ptr ,根據 c++ 標準庫一書總結
  • auto_ptr 的設計動機

void f()
{
	classA *p = new classA();
	...
	delete p;
}

如果我們忘記delete p 釋放資源那麼會造成內存泄露,
就算寫了 delete p
如果在函數體內 return 了,那麼delete 沒執行又泄露了
如果又有異常捕獲呢

void f()
{
	classA *p = new classA();
	
	try{
	...
	}
	catch(...){
	delete p;
	throw;
	}
	
	...
	delete p;
}

這纔是一個指針p 如果10個呢 那寫起來是不是很麻煩,而且還會造成代碼的複雜和累贅,
這不是優良的編程風格要儘量避免

如果是智能指針,情形就會大不相同

無論在任何情況下,只要自己被摧毀,就一定連帶釋放其所指向的資源,auto_ptr 就是這種智能型指針.

#include <memory>
void f()
{
	std::auto_ptr<classA> p(new classA);
}

ok 這樣函數就不用擔心忘記delete 或者return catch 了
注意一點:
auto_ptr 不允許使用一般指針的賦值方式初始化,不允許隱式轉換 explicit

std::auto_ptr<classA> p(new classA); 	//正確
std::auto_ptr<classA> p = new classA; 	//錯誤
  • auto_ptr 擁有權的轉移

auto_ptr 擁有嚴格的擁有權觀念,不能出現多個同時擁有多個對象的狀態,
也就是說 一個男人只能取一個老婆,不能同時多個男人同時取一個老婆,
那將會出亂子。auto_ptr 也是這樣,編譯器不會報錯,但是程序員要防範
這種錯誤.

std::auto_ptr<classA> p(new classA);
std::auto_ptr<classA> p2(p);

這時候 p 就把對象的擁有權交給p2了,這時的p是null 在使用它可能會造成意想不到的後果

std::auto_ptr<classA> p(new classA);
std::auto_ptr<classA> p2;
p2 = p;

賦值和上面的結果一樣,p的擁有權交給了p2,通俗講 p與老婆離婚了,他老婆跟了p2,這時的p也就是光棍null了,沒有對象了

如果auto_ptr 以 傳值(by value)的方式傳遞給某函數,那麼他的擁有權也交給了函數的形參

void f(std::auto_ptr<classA> t)
{
...
}

std::auto_ptr<classA> p(new classA);
f(p);

// 這時的 p 就是 null 了,在使用就會出現意想不到的問題

你可能認爲傳引用方式就萬事大吉了,然而這種方式更使擁有權捉摸不定,透過引用來獲得auto_ptr的函數,你根本無法預知擁有權是否被轉移,按引用傳遞auto_ptr是非常糟糕的設計,要全力避免

考慮到auto_ptr 的概念,我們可以運用 const &
這樣的話擁有權就不會發生改變了


void f(const auto_ptr<class A>& p)
{
	....
}

std::auto_ptr <classA> p(new classA);

f(p);

//p還可以使用,他的擁有權還有,const 修飾

如果是函數返回值傳遞的話,擁有權就轉移到函數調用端了

std::auto_ptr<classA> f()
{
	std::auto_ptr<classA> p(new classA);
	...
	return p;
}
  • auto_ptr 的運用實例

在這裏插入圖片描述

code:

// testSTL_auto_ptr.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
//


#include <iostream>
#include <memory>

template <class T>
std::ostream& operator<<(std::ostream& stream, const std::auto_ptr<T>& p)
{
	if (p.get() == NULL)
	{
		stream << "NULL";
	}
	else
	{
		stream << *p;
	}
	return stream;
}


int main()
{
	std::auto_ptr<int> p(new int(42));
	std::auto_ptr<int> q;

	std::cout << "after initialization:" << std::endl;
	std::cout << " p:" << p << std::endl;
	std::cout << " q:" << q << std::endl;

	q = p;
	std::cout << "after assigning auto pointers:" << std::endl;
	std::cout << " p:" << p << std::endl;
	std::cout << " q:" << q << std::endl;

	*q += 13;
	p = q;
	std::cout << "after change and reassignment:" << std::endl;
	std::cout << " p:" << p << std::endl;
	std::cout << " q:" << q << std::endl;

	system("pause");
}

運行結果:

after initialization:
 p:42
 q:NULL
after assigning auto pointers:
 p:NULL
 q:42
after change and reassignment:
 p:55
 q:NULL

注意:
std::ostream& operator<<(std::ostream& stream, const std::auto_ptr& p)
這個重載第二個參數是 const reference 所以不會發生擁有權的轉移

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章