有使用 C++ 做開發(fā)的童鞋應(yīng)該都經(jīng)歷過被 指針 折磨,使用指針的使用需要保證 new 和 delete 對(duì)齊,如果不注意使用很容易出現(xiàn)野指針、空指針和內(nèi)存泄漏等風(fēng)險(xiǎn)。我們應(yīng)該盡量避免使用指針,如果一定要用指針,推薦使用 C++ STL 提供智能指針,STL 的智能指針有 shared_ptr 和 unique_ptr。
shared_ptr
shared_ptr 是基于計(jì)數(shù)器技術(shù),一個(gè)對(duì)象可以被多個(gè) shared_ptr 指向,多個(gè) shared_ptr 共同維護(hù)一個(gè)共享的的引用計(jì)數(shù)器,當(dāng)計(jì)數(shù)器為 0 的時(shí)候自動(dòng)釋放對(duì)象,不需要通過delete進(jìn)行釋放。
class User {
public:
string name;
User(string name) {
this->name = name;
cout << "User:" << name << endl;
}
void say() {
cout << name << endl;
}
~User() {
cout << "~User:" << name << endl;
}
};
創(chuàng)建方式一
shared_ptr<User> user(new User("shared_ptr"));
創(chuàng)建方式二(推薦)
shared_ptr<User> user = make_shared<User>("make_shared");
使用指針
cout<<user->name<<endl;
user->say();
多個(gè) shared_ptr 指向一個(gè)對(duì)象
錯(cuò)誤?:多個(gè) shared_ptr 不能指向同一個(gè)原生對(duì)象
User *u = new User("shared_ptr");
shared_ptr<User> user1(u);
shared_ptr<User> user2(u); // 錯(cuò)誤,不被允許
正確?:可以通過拷貝方式實(shí)現(xiàn)
shared_ptr<User> user1(new User("shared_ptr"));
shared_ptr<User> user2 = user1;
指針傳遞
// 推薦寫法
void handle1(const shared_ptr<User> &user) {
user->say();
}
void handle2(const shared_ptr<User> user) {
user->say();
}
int main(){
shared_ptr<User> user = make_shared<User>("make_shared");
handle1(user);
handle2(user);
return 0;
}
unique_ptr
unique_ptr 是獨(dú)享的智能指針,一個(gè)對(duì)象只允許被一個(gè) unique_ptr 指向。
正確?
unique_ptr<User> user(new User("unique_ptr"));
正確?:推薦使用 make_unique
unique_ptr<User> user = make_unique<User>("unique_ptr");
錯(cuò)誤?:一個(gè)對(duì)象只允許被一個(gè) unique_ptr 指向。
User *u = new User("shared_ptr");
unique_ptr<User> user1(u);
unique_ptr<User> user2(u);
錯(cuò)誤?:unique_ptr 不支持拷貝
User *u = new User("shared_ptr");
unique_ptr<User> user1(u);
unique_ptr<User> user2 = user1;
指針傳遞
只允許通過值引用或者指針方式,不支持值傳遞,也可以通過 move 實(shí)現(xiàn)轉(zhuǎn)移。
void handle1(const unique_ptr<User> &user) {
user->say();
}
void handle2(const unique_ptr<User> user) {
user->say();
}
int main(){
unique_ptr<User> user(new User("unique_ptr"));
handle1(user);
// 錯(cuò)誤 handle2(user);
handle2(move(user));
return 0;
}
指針轉(zhuǎn)移
智能指針單獨(dú)使用是比較簡單的,不需要手動(dòng)對(duì)指針進(jìn)行釋放。如果需要在 vector 進(jìn)行使用,也是需要注意。
vector<unique_ptr<User>> users;
unique_ptr<User> user(new User("unique_ptr"));
users.push_back(move(user));
users[0]->say();
完整示例代碼
#include <iostream>
#include <vector>
using namespace std;
class User {
public:
string name;
User(string name) {
this->name = name;
cout << "User:" << name << endl;
}
void say() {
cout << name << endl;
}
~User() {
cout << "~User:" << name << endl;
}
};
void handle0(const shared_ptr<User> &user) {
user->say();
}
// 允許多個(gè) shared_ptr 指向同一個(gè)對(duì)象
void handle1(const shared_ptr<User> user) {
user->say();
}
// unique_ptr 不允許使用值傳遞,因?yàn)槭仟?dú)享的
void handle2(const unique_ptr<User> &user) {
user->say();
}
int main() {
shared_ptr<User> shared1(new User("shared_ptr"));
// 多個(gè) shared_ptr 不能指向同一個(gè)原生對(duì)象,如果需要多個(gè)shared_ptr指向同一個(gè)對(duì)象可以通過一下方式實(shí)現(xiàn)
const shared_ptr<User> shared2 = shared1;
// 推薦使用 make_shared 方式創(chuàng)建 shared_ptr
shared_ptr<User> make_shared1 = make_shared<User>("make_shared");
unique_ptr<User> unique1(new User("unique_ptr"));
unique_ptr<User> unique2 = make_unique<User>("make_unique");
// 不允許 unique_ptr<User> unique2 = unique1;
shared1->say();
make_shared1->say();
unique1->say();
handle0(shared2);
handle1(shared2);
handle1(make_shared1);
handle2(unique1);
handle2(unique2);
vector<unique_ptr<User>> users;
users.push_back(move(unique1));
users[0]->say();
return 0;
}