C++智慧指標auto_ptr使用講解
阿新 • • 發佈:2018-12-13
auto_ptr是C++98標準庫提供的一個智慧指標,但已被C++11明確宣告不再支援。
auto_ptr具有以下缺陷:
- auto_ptr有拷貝語義,拷貝後源物件變得無效,這可能引發很嚴重的問題;而unique_ptr則無拷貝語義,但提供了移動語義,這樣的錯誤不再可能發生,因為很明顯必須使用std::move()進行轉移。
#include <iostream>
#include <tr1/memory>
using namespace std::tr1;
using namespace std;
class A
{
public:
string id;
A (string id):id(id)
{
cout<<id<<":建構函式"<<endl;
}
~A()
{
cout<<id<<":解構函式"<<endl;
}
};
int main()
{
auto_ptr<A> auto_ap(new A("auto_ptr")),auto_bp;
cout<<auto_ap.get()<<endl;
auto_bp = auto_ap;
cout<< auto_ap.get()<<endl;
unique_ptr<A> unique_ap(new A("unique_ptr")),unique_bp;
cout<<unique_ap.get()<<endl;
// unique_bp = unique_ap; // 報錯
unique_bp = move(unique_ap);
cout<<unique_ap.get()<<endl;
return 0;
}
執行結果:
auto_ptr:建構函式 0x6115d0 0 unique_ptr:建構函式 0x6115f0 0 unique_ptr:解構函式 auto_ptr:解構函式
- auto_ptr不可作為容器元素,unique_ptr可以作為容器元素。因為auto_ptr的拷貝和賦值具有破壞性,不滿足容器要求:拷貝或賦值後,兩個物件必須具有相同值。
- auto_ptr不可指向動態陣列,unique_ptr可以指向動態陣列。因為unique_ptr有unique_ptr<T[]>過載版本,銷燬動態物件時呼叫delete[]。
#include <iostream>
#include <memory>
using namespace std;
class A
{
public:
string id;
A(string id):id(id)
{
cout<<id<<":建構函式"<<endl;
}
~A()
{
cout<<id<<":解構函式"<<endl;
}
};
int main()
{
//auto_ptr<A[]> auto_ap(new A[1]{A("unique_ptr")}); // 報錯
unique_ptr<A[]> unique_ap(new A[1]{A("unique_ptr")});
return 0;
}
- auto_ptr不可以自定義刪除器deleter,而unique_ptr可以。
#include <iostream>
#include <string>
#include <tr1/memory>
using namespace std;
using namespace std::tr1;
class A
{
public:
string id;
A(string id):id(id)
{
cout<<id<<":建構函式"<<endl;
}
~A()
{
cout<<id<<":解構函式"<<endl;
}
};
int main()
{
unique_ptr<A,void(*)(A*)> unique_ap(
new A[2]
{
A("unique_ptr0"),A("unique_ptr1")
},
[](A *a)
{
delete []a;
});
return 0;
}
執行結果:
unique_ptr0:建構函式
unique_ptr1:建構函式
unique_ptr1:解構函式
unique_ptr0:解構函式
#include <iostream>
#include <string>
#include <tr1/memory>
using namespace std;
using namespace std::tr1;
class Test
{
public:
Test(string s)
{
str = s;
cout<<"Test creat\n";
}
~Test()
{
cout<<"Test delete:"<<str<<endl;
}
string& getStr()
{
return str;
}
void setStr(string s)
{
str = s;
}
void print()
{
cout<<str<<endl;
}
private:
string str;
};
int main()
{
auto_ptr<Test> ptest(new Test("123"));
ptest->setStr("hello ");
ptest->print();
ptest.get()->print(); //成員函式get()返回一個原始的指標
ptest->getStr() += "world !";
(*ptest).print();
//Test creat
//Test delete:hello world !
ptest.reset(new Test("123")); //成員函式reset()重新繫結指向的物件,而原來的物件則會被釋放
ptest->print();
//ptest2會接管ptest原來的記憶體管理權,ptest會變為空指標,如果ptest2原來不為空,則它會釋放原來的資源
auto_ptr<Test> ptest2(new Test("456"));
ptest2 = ptest;
ptest2.release();
//ptest2->print(); //段錯誤 (核心已轉儲)
//判斷一個智慧指標是否為空不能使用if(ptest == NULL),應該使用if(ptest.get() == NULL)
if(ptest.get() == NULL)
{
cout<<"ptest = NULL\n";
}
//成員函式是release,這個函式只是把智慧指標賦值為空,但是它原來指向的記憶體並沒有被釋放,相當於它只是釋放了對資源的所有權
//ptest.release();
return 0;
}