new
和 new[]
的内存需要用 delete
和 delete[]
释放。delete
。new
出来的类,本身如何释放?unique_ptr
: C++ 11标准。shared_ptr
: C++ 11标准。weak_ptr
: C++ 11标准。auto_ptr
: C++98 标准,C++11 弃用,C++17 移除。scoped_ptr
: Boost中,STL未引入。unique_ptr
从 C++ 11 开始,定义在
中,独享它指向的对象,也就是说,同时只有一个 unique_ptr
指向同一个对象,当这个 unique_ptr
被销毁时,指向的对象也随之被销毁。
初始化
std::unique_ptr pu(new City("Shenzhen"));
std::make_unique
初始化(C++14 标准):std::unique_ptr pu = std::make_unique("Shenzhen");
City *p = new City("Shenzhen");
std::unique_ptr pu(p);
使用方法
*
和 ->
操作符,可以像使用指针一样使用 unique_ptr
。std::unique_ptr pu3 = std::make_unique("Shenzhen");
std::cout << "m_name = " << (*pu3).m_name << std::endl;
std::cout << "m_name = " << pu3->m_name << std::endl;
std::unique_ptr pu1(new City("Shenzhen"));
City *p = new City("Shenzhen");
// 错误,不能把普通指针直接赋值给智能指针。
std::unique_ptr pu2 = p;
// 错误,不能把普通指针直接赋值给智能指针。
std::unique_ptr pu3 = new City("Shenzhen");
// 错误,不能用其它的unique_ptr拷贝构造。
std::unique_ptr pu2 = pu1;
std::unique_ptr pu3;
pu3 = pu1;// 错误,不能用“=”对unique_ptr进行赋值。
unique_ptr
。City *p = new City("Shenzhen");
std::unique_ptr pu1(p);
// std::unique_ptr pu2(p); // 错误,不能把普通指针传给多个智能指针。
// std::unique_ptr pu3(p); // 错误,不能把普通指针传给多个智能指针
get()
方法返回裸指针。City *p = new City("Shenzhen");
std::unique_ptr pu(p);
std::cout << "p : " << p << std::endl;
std::cout << "pu.get(): " << pu.get() <
unique_ptr
管理不是 new
分配的内存。函数参数中使用unique_ptr
unique_ptr
没有拷贝构造函数,可以借助std::move()
)。不支持指针的运算(+
、-
、++
、--
)
其它技巧和陷阱
unique_ptr
赋值给另一个时,如果源 unique_ptr
是一个临时右值,编译器允许这样做; 如果源 unique_ptr
将存在一段时间,编译器禁止这样做。一般用于函数返回值。nullptr
给 unique_ptr
赋值将释放对象,空的 unique_ptr == nullptr
。release()
释放对原始指针的控制权,将 unique_ptr
置为空,返回裸指针。可用于把 unique_ptr
传递给子函数,子函数将负责释放对象。std::move()
可以转移对原始指针的控制权。可用于把 unique_ptr
传递给子函数,子函数形参也是 unique_ptr
。reset()
释放对象pu1.reset(); // 重置指向的原始指针,默认置为nullptr。
pu2.reset(nullptr);
pu3.reset(new City("Tianjing")); // 释放旧的原始指针,指向新的普通指针。
swap()
交换两个 unique_ptr
的控制权。std::unique_ptr pu1(new City("ShenZhen"));
std::unique_ptr pu2(new City("Beijing"));
pu1.swap(pu2);
unique_ptr
也可像普通指针那样,当指向一个类继承体系的基类对象时,也具有多态性质,如同使用裸指针管理基类对象和派生类对象那样。unique_ptr
不是绝对安全。如程序用 exit()
退出,全局 unique_ptr
可自动释放,但局部非 static
unique_ptr
无法释放。 操作空的 unique_ptr
也有可能出现野指针的情况。unique_ptr
提供支持数组的具体化版本,数组版本的 unique_ptr
,重载操作符 []
,操作符 []
返回的是引用,可以作为左值使用。shared_ptr
shared_ptr
共享它指向的对象,多个 shared_ptr
可指向(关联)相同对象,在内部采用计数机制来实现。当新的 shared_ptr
与对象关联时,引用计数增加 1
。shared_ptr
超出作用域时,引用计数减 1
。当引用计数变为 0
时,则表示没有shared_ptr
与对象关联,则释放该对象。shared_ptr
的构造函数也是 explicit
,但没有删除拷贝构造函数和赋值函数。
初始化
分配内存并初始化:
City *p = new City("Shenzhen");
std::shared_ptr p0(p);
C++11 标准,效率更高。
std::shared_ptr p0(new City("Shenzhen"));
用已存在的地址初始化:
std::shared_ptr p0 = std::make_shared("Shenzhen");
用已存在的 shared_ptr
初始化,计数加1。
std::shared_ptr p0(new City("Shenzhen"));
std::shared_ptr p1(p0);
std::shared_ptr p2 = p0;
使用方法
*
和->
操作符,可像使用指针一样使用 shared_ptr
。use_count()
方法返回引用计数器的值。unique()
方法,如果 use_count()
为 1
,返回 true
, 否则返回false
。shared_ptr
的计数器减 1
,右值shared_ptr
计数器加 1
。get()
方法返回裸指针。shared_ptr
。shared_ptr
管理不是 new
分配的内存。函数参数中使用 shared_ptr
不支持指针的运算(+
、-
、++
、--
)
其它技巧和陷阱
unique_ptr
不一样)。nullptr
给 shared_ptr
赋值将把计数器减 1
,如果计数器为 0
,将释放对象,空的 shared_ptr == nullptr
。release()
成员函数(与 unique_ptr
不一样)。std::move()
可以转移对原始指针的控制权。可将 unique_ptr
转移成 shared_ptr
。reset()
改变与资源的关联关系。pp.reset(); // 解除与资源的关系,资源的引用计数器减1。
pp.reset(new City("Shenzhen")); //解除与资源的关系,资源的引用计数减1,并关联新的资源。
swap()
交换两个 shared_ptr
的控制权。shared_ptr
也可像普通指针那样,当指向一个类继承体系的基类对象时,也具有多态的性质,如同使用裸指针管理基类对象和派生类对象那样。shared_ptr
不是绝对安全,如果程序中调用 exit()
退出,全局的 shared_ptr
可自动释放,但局部非 static
shared_ptr
无法释放。shared_ptr
提供了支持数组的具体化版本。shared_ptr
,重载了操作符 []
,操作符 []
返回的是引用,可以作为左值使用。shared_ptr
线程安全性:shared_ptr
引用计数本身是线程安全(引用计数是原子操作)。shared_ptr
对象是线程安全的。shared_ptr
对象进行读和写,则需要加锁。shared_ptr
所指同一对象,不管是相同 shared_ptr
对象,还是不同 shared_ptr
对象,也需要加锁。unique_ptr
能解决问题,就不要用 shared_ptr
。unique_ptr
效率更高,占用资源更少。weak_ptr
shared_ptr 存在的问题
shared_ptr
内部维护一个共享引用计数器,多个 shared_ptr
可指向同一资源。如果出现了循环引用情况,引用计数永远无法归 0
,资源不会被释放。
为什么引入 weak_ptr
?
weak_ptr
为配合 shared_ptr
而引入,指向一个由 shared_ptr
管理的资源,但不影响资源生命周期。 换言之,将一 weak_ptr
绑定到一 shared_ptr
不会改变 shared_ptr
的引用计数。 不论是否有 weak_ptr
指向,如果最后一个指向资源的 shared_ptr
被销毁,资源就会被释放。 weak_ptr
更像是 shared_ptr
助手。
使用方法
weak_ptr
没有重载 ->
和 *
操作符,不能直接访问资源。operator=(); // 把 shared_ptr 或 weak_ptr 赋值给 weak_ptr。
expired(); // 判断它指向的资源是否已过期(过期则销毁)。
lock(); // 返回 shared_ptr, 如果资源已过期,返回空的 shared_ptr。
reset(); // 将当前 weak_ptr 指针置为空。
swap(); // 交换。
weak_ptr
不控制对象生命周期,但知道对象是否还活着。lock()
函数可提升为 shared_ptr
。shared_ptr
。shared_ptr
。lock()
提升行为线程安全。默认情况下,智能指针过期时,用 delete
释放原始指针。程序员可以自定义删除器,改变智能指针释放资源的行为。删除器可以是全局函数、仿函数和Lambda表达式,形参为原始指针。
void DeleteFunction(City *city) // 删除器,普通函数
{
std::cout << "DeleteFunction(" << city->m_name << ")" << std::endl;
delete city;
}
struct DeleteClass // 删除器,仿函数
{
void operator()(City *city)
{
std::cout << "DeleteClass(" << city->m_name << ")" << std::endl;
delete city;
}
};
auto DeleteLambda = [](City *city) { // 删除器,Lambda表达式
std::cout << "DeleteLambda(" << city->m_name << ")" << std::endl;
delete city;
};
int main(void)
{
// std::shared_ptr pa1(new City("Shenzhen")); // 使用缺省的删除器,即用delete关键字删除。
// std::shared_ptr pa2(new City("Beijing"), DeleteFunction); // 删除器,普通函数。
// std::shared_ptr pa3(new City("Shanghai"), DeleteClass()); // 删除器,仿函数。
// std::shared_ptr pa4(new City("Guangzhou"), DeleteLambda); // 删除器,Lambda表达式。
// std::unique_ptr pu0(new City("Shenzhen"));
std::unique_ptr pu1(new City("Beijing"), DeleteFunction);
// std::unique_ptr pu2(new City("Shanghai"), DeleteFunction);
// std::unique_ptr pu3(new City("Guangzhou"), DeleteClass());
// std::unique_ptr pu4(new City("Tianjin"), DeleteLambda);
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_deleter.cpp && ./a.out
City(Beijing)
DeleteFunction(Beijing)
~City(Beijing)
jiazhao@MININT-04QBDDV:~/samples$
基于 City
类进行测试,代码如下:
#include
#include
class City
{
public:
std::string m_name;
City()
{
std::cout << "City()" << std::endl;
}
City(std::string name) : m_name(name)
{
std::cout << "City(" << m_name << ")" << std::endl;
}
~City()
{
std::cout << "~City(" << m_name << ")" << std::endl;
}
};
int main(void)
{
// 方法一:
City *p = new City("Shenzhen");
std::unique_ptr pu1(p);
std::cout << "m_name = " << (*p).m_name << std::endl;
std::cout << "m_name = " << p->m_name << std::endl;
// 方法二:
std::unique_ptr pu2(new City("Shenzhen"));
// 方法三 (std::make_unique C++14 标准):
std::unique_ptr pu3 = std::make_unique("Shenzhen");
// 智能指针重载了 `*` 和 `->` 操作符,可以像使用指针一样使用 `unique_ptr`。
std::cout << "m_name = " << (*pu3).m_name << std::endl;
std::cout << "m_name = " << pu3->m_name << std::endl;
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_unique_ptr.cpp && ./a.out
City(Shenzhen)
m_name = Shenzhen
m_name = Shenzhen
City(Shenzhen)
City(Shenzhen)
m_name = Shenzhen
m_name = Shenzhen
~City(Shenzhen)
~City(Shenzhen)
~City(Shenzhen)
jiazhao@MININT-04QBDDV:~/samples$
int main ()
{
std::unique_ptr pu1(new City("Shenzhen"));
City *p = new City("Beijing");
// std::unique_ptr pu2 = p; // 错误,不能把普通指针直接赋值给智能指针。
// std::unique_ptr pu3 = new City("Shenzhen"); // 错误,不能把普通指针直接赋值给智能指针。
// std::unique_ptr pu2 = pu1; // 错误,不能用其它的unique_ptr拷贝构造。
std::unique_ptr pu3;
// pu3 = pu1; // 错误,不能用“=”对unique_ptr进行赋值。
// delete p; // 注释掉不会析构
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_unique_ptr.cpp && ./a.out
City(Shenzhen)
City(Shenzhen)
~City(Shenzhen)
jiazhao@MININT-04QBDDV:~/samples$
unique_ptr
。int main(void)
{
City *p = new City("Shenzhen");
std::unique_ptr pu1(p);
std::unique_ptr pu2(p); // 错误,不能把普通指针传给多个智能指针。
std::unique_ptr pu3(p); // 错误,不能把普通指针传给多个智能指针。
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_unique_ptr.cpp && ./a.out
City(Shenzhen)
~City(Shenzhen)
Segmentation fault
jiazhao@MININT-04QBDDV:~/samples$
get()
方法返回裸指针。int main (void)
{
City *p = new City("Shenzhen");
std::unique_ptr pu(p);
std::cout << "p : " << p << std::endl;
std::cout << "pu.get(): " << pu.get() << std::endl;
std::cout << "&pu : " << &pu << std::endl;
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_unique_ptr.cpp && ./a.out
City(Shenzhen)
p : 0x560cb7efbeb0
pu.get(): 0x560cb7efbeb0
&pu : 0x7ffd7495e9d0
~City(Shenzhen)
jiazhao@MININT-04QBDDV:~/samples$
unique_ptr
// 1) 传引用: BeautifulCity(pu);
void BeautifulCity1(std::unique_ptr &pp)
{
std::cout << "&pp, m_name: " << pp->m_name << std::endl;
}
// 2)传值: 删除了拷贝构造,不能直接传值,可用:BeautifulCity(std::move(pu));
void BeautifulCity2(std::unique_ptr pp)
{
std::cout << "pp, m_name: " << pp->m_name << std::endl;
}
// 3) 传指针:BeautifulCity3(&pu)
void BeautifulCity3(std::unique_ptr *pp)
{
std::cout << "*pp, m_name: " << (*pp)->m_name << std::endl;
}
int main(void)
{
std::unique_ptr pu1(new City("Shenzhen"));
std::unique_ptr pu2(new City("Shenzhen"));
std::unique_ptr pu3(new City("Shenzhen"));
BeautifulCity1(pu1);
// BeautifulCity2(pu2); // 错误,删除了拷贝构造,不能直接赋值。
BeautifulCity2(std::move(pu2));
BeautifulCity3(&pu3);
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_unique_ptr.cpp && ./a.out
City(Shenzhen)
City(Shenzhen)
City(Shenzhen)
&pp, m_name: Shenzhen
pp, m_name: Shenzhen
~City(Shenzhen)
*pp, m_name: Shenzhen
~City(Shenzhen)
~City(Shenzhen)
jiazhao@MININT-04QBDDV:~/samples$
unique_ptr
赋值给另一个时,如果源 unique_ptr
是一个临时右值,编译器允许这样做; 如果源 unique_ptr
将存在一段时间,编译器禁止这样做。一般用于函数返回值。std::unique_ptr GetCity()
{
std::unique_ptr pu(new City("Shanghai"));
return pu;
}
int main (void)
{
std::unique_ptr pu1(new City("Shenzhen"));
std::unique_ptr pu2;
// pu2 = pu1; // 错误
pu2 = std::unique_ptr(new City("Beijing")); // 用匿名对象赋值
std::cout << "before" << std::endl;
pu2 = GetCity();
std::cout << "after" << std::endl;
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_unique_ptr.cpp && ./a.out
City(Shenzhen)
City(Beijing)
before
City(Shanghai)
~City(Beijing)
after
~City(Shanghai)
~City(Shenzhen)
jiazhao@MININT-04QBDDV:~/samples$
nullptr
给 unique_ptr
赋值将释放对象,空的 unique_ptr == nullptr
。int main(void)
{
std::unique_ptr pu(new City("Shenzhen"));
std::cout << (pu == nullptr ? "Empty." : "Not empty.") << std::endl;
pu = nullptr;
std::cout << (pu == nullptr ? "Empty." : "Not empty.") << std::endl;
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_unique_ptr.cpp && ./a.out
City(Shenzhen)
Not empty.
~City(Shenzhen)
Empty.
jiazhao@MININT-04QBDDV:~/samples$
release()
释放对原始指针的控制权,将 unique_ptr
置为空,返回裸指针。可用于把 unique_ptr
传递给子函数,子函数将负责释放对象。std::move()
可以转移对原始指针的控制权。可用于把 unique_ptr
传递给子函数,子函数形参也是 unique_ptr
。void VisitCity1(const City* city)
{
std::cout << "VisitCity1: " << city->m_name << std::endl;
}
void VisitCity2(City* city)
{
std::cout << "VisitCity2: " << city->m_name << std::endl;
delete city;
}
void VisitCity3(const std::unique_ptr& pu)
{
std::cout << "VisitCity3: " << pu->m_name << std::endl;
}
void VisitCity4(std::unique_ptr pu)
{
std::cout << "VisitCity4: " << pu->m_name << std::endl;
}
int main(void)
{
std::unique_ptr pu(new City("Shenzhen"));
std::cout << "Start..." << std::endl;
// VisitCity1(pu.get()); // 把原始指针传给子函数,不释放控制权,子函数不能释放原始指针。
VisitCity2(pu.release()); // 把原始指针传给子函数,释放控制权,由子函数释放原始指针。
// VisitCity3(pu); // 引用传递。
// VisitCity4(std::move(pu)); // 值传递,要借助std::move。
std::cout << "End." <
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_unique_ptr.cpp && ./a.out
City(Shenzhen)
Start...
VisitCity2: Shenzhen
~City(Shenzhen)
End.
jiazhao@MININT-04QBDDV:~/samples$
reset()
释放对象// void reset(T* _ptr = (T*)nullptr);
int main(void)
{
std::unique_ptr pu1(new City("Shenzhen"));
std::cout << "pu1: " << pu1.get() << std::endl;
pu1.reset(); // 重置指向的原始指针,默认置为nullptr。
std::cout << "pu1: " << pu1.get() << std::endl;
std::unique_ptr pu2(new City("Beijing"));
std::cout << "pu2: " << pu2.get() << std::endl;
pu2.reset(nullptr);
std::cout << "pu2: " << pu2.get() << std::endl;
std::unique_ptr pu3(new City("Shanghai"));
std::cout << "pu3: " << pu3.get() << std::endl;
pu3.reset(new City("Tianjing")); // 释放旧的原始指针,指向新的普通指针。
std::cout << "pu3: " << pu3.get() << std::endl;
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_unique_ptr.cpp && ./a.out
City(Shenzhen)
pu1: 0x55e436bf6eb0
~City(Shenzhen)
pu1: 0
City(Beijing)
pu2: 0x55e436bf6eb0
~City(Beijing)
pu2: 0
City(Shanghai)
pu3: 0x55e436bf6eb0
City(Tianjing)
~City(Shanghai)
pu3: 0x55e436bf72f0
~City(Tianjing)
jiazhao@MININT-04QBDDV:~/samples$
swap()
交换两个 unique_ptr
的控制权。int main(void)
{
std::unique_ptr pu1(new City("ShenZhen"));
std::unique_ptr pu2(new City("Beijing"));
std::cout << "pu1: " << pu1.get() << std::endl;
std::cout << "pu2: " << pu2.get() << std::endl;
pu1.swap(pu2);
std::cout << "pu1: " << pu1.get() << std::endl;
std::cout << "pu2: " << pu2.get() << std::endl;
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_unique_ptr.cpp && ./a.out
City(ShenZhen)
City(Beijing)
pu1: 0x556cc09b6eb0
pu2: 0x556cc09b72f0
pu1: 0x556cc09b72f0
pu2: 0x556cc09b6eb0
~City(ShenZhen)
~City(Beijing)
jiazhao@MININT-04QBDDV:~/samples$
unique_ptr
也可像普通指针那样,当指向一个类继承体系的基类对象时,也具有多态性质,如同使用裸指针管理基类对象和派生类对象那样。class Car
{
public:
virtual void Driving()
{
std::cout << "Driving." << std::endl;
}
virtual void Parking()
{
std::cout << "Parking." << std::endl;
}
virtual void Washing()
{
std::cout << "Washing." << std::endl;
}
};
class Biyadi : public Car
{
public:
void Driving() override
{
std::cout << "Driving Biyadi." << std::endl;
}
void Parking() override
{
std::cout << "Parking Biyadi." << std::endl;
}
void Washing() override
{
std::cout << "Washing Biyadi." << std::endl;
}
};
class Xiaopeng : public Car
{
public:
void Driving() override
{
std::cout << "Driving Xiaopeng." << std::endl;
}
void Parking() override
{
std::cout << "parking Xiaopeng." << std::endl;
}
void Washing() override
{
std::cout << "Washing Xiaopeng." << std::endl;
}
};
class Weilai : public Car
{
public:
void Driving() override
{
std::cout << "Driving Weilai." << std::endl;
}
void Parking() override
{
std::cout << "parking Weilai." << std::endl;
}
void Washing() override
{
std::cout << "Washing Weilai." << std::endl;
}
};
int main(void)
{
int id = 0;
std::cout << "Input: (1 - Biyadi, 2 - Xiaopeng, 3 - Weilai): ";
std::cin >> id;
std::unique_ptr pu;
if (id == 1)
{
pu = std::unique_ptr(new Biyadi);
}
if (id == 2)
{
pu = std::unique_ptr(new Xiaopeng);
}
if (id == 3)
{
pu = std::unique_ptr(new Weilai);
}
if (pu != nullptr)
{
pu->Driving();
pu->Parking();
pu->Washing();
}
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_unique_ptr.cpp && ./a.out
Input: (1 - Biyadi, 2 - Xiaopeng, 3 - Weilai): 2
Driving Xiaopeng.
parking Xiaopeng.
Washing Xiaopeng.
jiazhao@MININT-04QBDDV:~/samples$
unique_ptr
不是绝对安全。exit()
退出,全局 unique_ptr
可自动释放,但局部非 static
unique_ptr
无法释放。unique_ptr
也有可能出现野指针的情况。std::unique_ptr g_pu(new City("Shenzhen"));
int main(void)
{
std::unique_ptr pu(new City("Beijing")); // 不会自动释放
static std::unique_ptr s_pu(new City("Shanghai")); // 会释放,全局静态区
exit(0); // 局部智能指针pu不会释放
// return 0; // 全局和局部的智能指针都会释放
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_unique_ptr.cpp && ./a.out
City(Shenzhen)
City(Beijing)
City(Shanghai)
~City(Shanghai)
~City(Shenzhen)
jiazhao@MININT-04QBDDV:~/samples$
unique_ptr
提供支持数组的具体化版本,数组版本的 unique_ptr
,重载操作符 []
,操作符 []
返回的是引用,可以作为左值使用。int main(void)
{
// City *parr1 = new City[2];
// // City *parr1 = new City[2]{std::string(""), std::string("")};
// parr1[0].m_name = "Shenzhen";
// parr1[1].m_name = "Beijing";
// std::cout << parr1[0].m_name << std::endl;
// std::cout << parr1[1].m_name << std::endl;
// delete [] parr1;
// std::unique_ptr parr2(new City[2]);
std::unique_ptr parr2(new City[2]{std::string("Shenzhen"), std::string("Beijing")});
parr2[0].m_name = "Shenzhen";
parr2[1].m_name = "Beijing";
std::cout << parr2[0].m_name << std::endl;
std::cout << parr2[1].m_name << std::endl;
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_unique_ptr.cpp && ./a.out
City(Shenzhen)
City(Beijing)
Shenzhen
Beijing
~City(Beijing)
~City(Shenzhen)
jiazhao@MININT-04QBDDV:~/samples$
#include
#include
class City
{
public:
std::string m_name;
City()
{
std::cout << "City()" << std::endl;
}
City(std::string name) : m_name(name)
{
std::cout << "City(" << m_name << ")" << std::endl;
}
~City()
{
std::cout << "~City(" << m_name << ")" << std::endl;
}
};
int main (void)
{
// // 方法一:
// City *p = new City("Shenzhen");
// std::shared_ptr p0(p);
// // 方法二:
// std::shared_ptr p0(new City("Shenzhen"));
// 方法三:
std::shared_ptr p0 = std::make_shared("Shenzhen");
// 方法四:
std::shared_ptr p1(p0);
std::shared_ptr p2 = p0;
std::cout << "p0.use_count() = " << p0.use_count() << std::endl;
std::cout << "p0->m_name = " << p0->m_name << std::endl;
std::cout << "p0.get() = " << p0.get() << std::endl;
std::cout << "p1.use_count() = " << p1.use_count() << std::endl;
std::cout << "p1->m_name = " << p1->m_name << std::endl;
std::cout << "p1.get() = " << p1.get() << std::endl;
std::cout << "p2.use_count() = " << p2.use_count() << std::endl;
std::cout << "p2->m_name = " << p2->m_name << std::endl;
std::cout << "p2.get() = " << p2.get() << std::endl;
std::cout << "p2.unique() = " << p2.unique() << std::endl;
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_shared_ptr.cpp && ./a.out
City(Shenzhen)
p0.use_count() = 3
p0->m_name = Shenzhen
p0.get() = 0x555d01152ec0
p1.use_count() = 3
p1->m_name = Shenzhen
p1.get() = 0x555d01152ec0
p2.use_count() = 3
p2->m_name = Shenzhen
p2.get() = 0x555d01152ec0
p2.unique() = 0
~City(Shenzhen)
jiazhao@MININT-04QBDDV:~/samples$
shared_ptr
的计数器减1
,右值shared_ptr
计数器加 1
。int main(void)
{
std::shared_ptr pa0(new City("Shenzhen")); // 初始化shared_ptr
std::shared_ptr pa1 = pa0; // 拷贝构造,计数器加1
std::shared_ptr pa2 = pa0; // 拷贝构造,计数器加1
std::cout << "pa0.use_count() = " << pa0.use_count() << std::endl; // 值为3
std::shared_ptr pb0(new City("Beijing"));
std::shared_ptr pb1 = pb0;
std::cout << "pb0.use_count() = " << pb0.use_count() << std::endl; // 值为2
pb1 = pa1;
std::cout << "pa0.use_count() = " << pa0.use_count() << std::endl; // 值为4
std::cout << "pb0.use_count() = " << pb0.use_count() << std::endl; // 值为1
pb0 = pa1; // 计数器变为0,会释放pb0,即调用析构函数 ~City(Beijing)。
std::cout << "pa0.use_count() = " << pa0.use_count() << std::endl; // 值为5
std::cout << "pb0.use_count() = " << pb0.use_count() << std::endl; // 值为5
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_shared_ptr.cpp && ./a.out
City(Shenzhen)
pa0.use_count() = 3
City(Beijing)
pb0.use_count() = 2
pa0.use_count() = 4
pb0.use_count() = 1
~City(Beijing)
pa0.use_count() = 5
pb0.use_count() = 5
~City(Shenzhen)
jiazhao@MININT-04QBDDV:~/samples$
shared_ptr
内部维护一个共享引用计数器,多个 shared_ptr
可指向同一资源。如果出现了循环引用情况,引用计数永远无法归 0
,资源不会被释放。#include
#include
class Country; //Country 类要提前声明。
class City
{
public:
std::string m_name;
std::shared_ptr m_p;
City()
{
std::cout << "City()" << std::endl;
}
City(std::string name) : m_name(name)
{
std::cout << "City(" << m_name << ")" << std::endl;
}
~City()
{
std::cout << "~City(" << m_name << ")" << std::endl;
}
};
class Country
{
public:
std::string m_name;
std::shared_ptr m_p;
Country()
{
std::cout << "Country()" << std::endl;
}
Country(std::string name) : m_name(name)
{
std::cout << "Country(" << m_name << ")" << std::endl;
}
~Country()
{
std::cout << "~Country(" << m_name << ")" << std::endl;
}
};
int main(void)
{
std::shared_ptr pa = std::make_shared("Shenzhen");
std::shared_ptr pb = std::make_shared("China");
pa->m_p = pb;
pb->m_p = pa;
std::cout << "pa.use_count() = " << pa.use_count() << std::endl; // 引用计数器为2,main函数退出时不析构
std::cout << "pb.use_count() = " << pb.use_count() << std::endl; // 引用计数器为2,main函数退出时不析构
// 解决方法用std::weak_ptr
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_weak_ptr.cpp && ./a.out
City(Shenzhen)
Country(China)
pa.use_count() = 2
pb.use_count() = 2
jiazhao@MININT-04QBDDV:~/samples$
weak_ptr
。#include
#include
class Country;
class City
{
public:
std::string m_name;
std::weak_ptr m_p; // 改成 weak_ptr
City()
{
std::cout << "City()" << std::endl;
}
City(std::string name) : m_name(name)
{
std::cout << "City(" << m_name << ")" << std::endl;
}
~City()
{
std::cout << "~City(" << m_name << ")" << std::endl;
}
};
class Country
{
public:
std::string m_name;
std::weak_ptr m_p; // 改成 weak_ptr
Country()
{
std::cout << "Country()" << std::endl;
}
Country(std::string name) : m_name(name)
{
std::cout << "Country(" << m_name << ")" << std::endl;
}
~Country()
{
std::cout << "~Country(" << m_name << ")" << std::endl;
}
};
int main(void)
{
std::shared_ptr pa = std::make_shared("Shenzhen");
std::shared_ptr pb = std::make_shared("China");
pa->m_p = pb; // weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。
pb->m_p = pa;
std::cout << "pa.use_count() = " << pa.use_count() << std::endl; // 引用计数器为1, 可以正常析构
std::cout << "pb.use_count() = " << pb.use_count() << std::endl; // 引用计数器为1, 可以正常析构
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_weak_ptr.cpp && ./a.out
City(Shenzhen)
Country(China)
pa.use_count() = 1
pb.use_count() = 1
~Country(China)
~City(Shenzhen)
jiazhao@MININT-04QBDDV:~/samples$
lock()
函数提升为 shared_ptr
。int main(void)
{
std::shared_ptr pa = std::make_shared("Shenzhen");
{
std::shared_ptr pb = std::make_shared("China");
pa->m_p = pb;
pb->m_p = pa;
// 非线程安全
if (pa->m_p.expired() == true)
{
std::cout << "pa->m_p.expired() = true" << std::endl;
}
else
{
std::cout << "pa->m_p.lock()->m_name = " << pa->m_p.lock()->m_name << std::endl;
}
}
if (pa->m_p.expired() == true)
{
std::cout << "pa->m_p.expired() = true" << std::endl;
}
else
{
std::cout << "pa->m_p.lock()->m_name = " << pa->m_p.lock()->m_name << std::endl;
}
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_weak_ptr.cpp && ./a.out
City(Shenzhen)
Country(China)
pa->m_p.lock()->m_name = China
~Country(China)
pa->m_p.expired() = true
~City(Shenzhen)
jiazhao@MININT-04QBDDV:~/samples$
lock()
提升行为线程安全。int main(void)
{
std::shared_ptr pa = std::make_shared("Shenzhen");
{
std::shared_ptr pb = std::make_shared("China");
pa->m_p = pb;
pb->m_p = pa;
std::shared_ptr pp = pa->m_p.lock(); // 线程安全/原子操作。
if (pp == nullptr)
{
std::cout << "pa->m_p.lock() = nullptr" << std::endl;
}
else
{
std::cout << "pa->m_p.lock()->m_name = " << pp->m_name << std::endl;
}
}
std::shared_ptr pp = pa->m_p.lock(); // pb 生命周期结束,此处返回空。
if (pp == nullptr)
{
std::cout << "pa->m_p.lock() = nullptr" << std::endl;
}
else
{
std::cout << "pa->m_p.lock()->m_name = " << pp->m_name << std::endl;
}
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_weak_ptr.cpp && ./a.out
City(Shenzhen)
Country(China)
pa->m_p.lock()->m_name = China
~Country(China)
pa->m_p.lock() = nullptr
~City(Shenzhen)
jiazhao@MININT-04QBDDV:~/samples$
#include
#include
class City
{
public:
std::string m_name;
City()
{
std::cout << "City()" << std::endl;
}
City(std::string name) : m_name(name)
{
std::cout << "City(" << m_name << ")" << std::endl;
}
~City()
{
std::cout << "~City(" << m_name << ")" << std::endl;
}
};
void DeleteFunction(City *city) // 删除器,普通函数
{
std::cout << "DeleteFunction(" << city->m_name << ")" << std::endl;
delete city;
}
struct DeleteClass // 删除器,仿函数
{
void operator()(City *city)
{
std::cout << "DeleteClass(" << city->m_name << ")" << std::endl;
delete city;
}
};
auto DeleteLambda = [](City *city) { // 删除器,Lambda表达式
std::cout << "DeleteLambda(" << city->m_name << ")" << std::endl;
delete city;
};
int main(void)
{
// std::shared_ptr pa1(new City("Shenzhen")); // 使用缺省的删除器,即用delete关键字删除。
// std::shared_ptr pa2(new City("Beijing"), DeleteFunction); // 删除器,普通函数。
// std::shared_ptr pa3(new City("Shanghai"), DeleteClass()); // 删除器,仿函数。
// std::shared_ptr pa4(new City("Guangzhou"), DeleteLambda); // 删除器,Lambda表达式。
// std::unique_ptr pu0(new City("Shenzhen"));
std::unique_ptr pu1(new City("Beijing"), DeleteFunction);
// std::unique_ptr pu2(new City("Shanghai"), DeleteFunction);
// std::unique_ptr pu3(new City("Guangzhou"), DeleteClass());
// std::unique_ptr pu4(new City("Tianjin"), DeleteLambda);
return 0;
}
输出:
jiazhao@MININT-04QBDDV:~/samples$ g++ smart_pointer_deleter.cpp && ./a.out
City(Beijing)
DeleteFunction(Beijing)
~City(Beijing)
jiazhao@MININT-04QBDDV:~/samples$