C++智能指針之不帶引用計數的智能指針(auto_ptr、scoped_ptr、unique_ptr),以及他們是如何解決淺拷貝問題?

  1. auto_ptr:c++11前就存在於c++庫中
int main(){
    auto_ptr<int> ptr1(new int);
    auto_ptr<int> ptr2(ptr1);
    //拷貝構造ptr2,ptr1底層的裸指針會被置爲nullptr,ptr1底層裸指針原來的指向賦值給了ptr2的裸指針
    return 0;
}

1.auto_ptr拷貝構造函數:
auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }

2.拷貝構造函數調用release()方法,轉移裸指針的所有權:
element_type*release() throw()
{
	element_type* __tmp = _M_ptr;
	_M_ptr = 0;
	return __tmp;
}

總結:在涉及到較多賦值和拷貝構造的場景下,不要使用auto_ptr,這個指針很危險。

  1. scoped_ptr:c++11新增:
 #include <boost/scoped_ptr.hpp>
 using namespace boost;
int main(){
    boost::scoped_ptr<int> ptr1(new int);
    //boost::scoped_ptr<int> ptr2(ptr1);//不允許,編譯無法通過
    return 0;
}

scoped_ptr的拷貝構造函數和賦值運算符重載函數都被deletescoped_ptr(const scoped_ptr<T>&) = delete;
scoped_ptr<T>& operator=(const scoped_ptr<T>&) = delete;

總結:scoped_ptr從引用一個資源開始,從一而終,不能用來拷貝構造不能賦值。

  1. unique_ptr:c++11新增:
unique_ptr的拷貝構造函數和賦值運算符重載函數都被deleteunique_ptr(const unique_ptr<T>&) = delete;
unique_ptr<T>& operator=(const unique_ptr<T>&) = delete;

不同的是,unique_ptr提供了帶右值參數的拷貝構造函數和賦值運算符重載函數:
int main(){
    unique_ptr<int> ptr1(new int);
    //unique_ptr<int> ptr2(ptr1);無法調用unique_ptr帶左值參數的拷貝構造
    unique_ptr<int> ptr2(std::move(ptr1));//調用unique_ptr帶右值參數的拷貝構造函數
    return 0;
}
這裏是ptr1把自己的資源都移交給了ptr2,所以,ptr1中的資源我們就不能再去訪問了,

總結:我們顯示的使用帶右值引用的拷貝構造和賦值運算符重載,其實也是在提醒我們開發者,既然拷貝構造新對象了,原來的資源就不要去訪問了,因爲指針指向的資源已經被轉移到新對象上了,即ptr1 --> ptr2.

如果需要使用不帶引用計數的智能指針,推薦使用unique_ptr,這樣更安全,更高效。

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