uot; << vect[x]->GetName() << std::endl;
}
std::system("pause");
return 0;
}
智能指针同样支持使用引用计数器功能,在指针内部读者可通过使用ptr.use_count()
来输出当前的计数器,当此处代码没有被使用是则引用计数器会为0,而当代码或多个进程使用时则引用计数器相应的会增加,查询引用计数器可以如下所示;
#include <iostream>
#include <string>
#include <boost/shared_ptr.hpp>
using namespace std;
using namespace boost;
class MyShared
{
private:
boost::shared_ptr<int> ptr;
public:
MyShared(boost::shared_ptr<int> p_) :ptr(p_){}
void print()
{
cout << "内部 计数: " << ptr.use_count() << " 数值: " << *ptr << endl;
}
};
// 自动拷贝一个对象,所以引用计数会+1
void print_func(boost::shared_ptr<int> ptr)
{
cout << "外部 计数: " << ptr.use_count() << " 数值: " << *ptr << endl;
}
int main(int argc, char const *argv[])
{
boost::shared_ptr<int> ptr(new int(100)); // 定义整数指针
MyShared s1(ptr), s2(ptr); // 定义两个对象,并初始化
s1.print();
s2.print();
*ptr = 200;
print_func(ptr);
s1.print();
s2.print();
std::system("pause");
return 0;
}
如上,在声明了shared_ptr
和两个MyShared
类后,指针被共享,因此引用计数为3,调用print_func()
函数,该函数内部拷贝了一个shared_ptr
对象,因此引用计数再次增加1,但退出函数时,拷贝自动析构,引用计数又会恢复为3。
2.4 使用MakeShared工厂函数
boost::make_shared是一个工厂函数,用于动态分配一个对象并返回一个智能指针,它是Boost库中的一个组件。使用make_shared
我们可以将对象的构造和内存分配合并在一起,避免了常规构造函数和动态内存分配的性能损失和代码冗余。
当读者使用2.3节中所示的shared_ptr
智能指针时,虽然能够很好的消除delete
释放的调用,但我们还是需要使用new
方法来构造初始化数据集,为了能够不再使用new
关键字,在smart_ptr
库中提供了一个工厂函数make_shared()
函数,用于消除使用new
创建数据集,工厂函数常用于初始化特定的指针数据,如下所示;
#include <iostream>
#include <string>
#include <vector>
#include <boost/smart_ptr.hpp>
using namespace std;
using namespace boost;
int main(int argc, char const *argv[])
{
// make_shared 工厂函数初始化
boost::shared_ptr<string> string_ptr = boost::make_shared<string>("hello lyshark");
cout << "初始化字符串: " << *string_ptr << endl;
// 应用于标准容器中
typedef std::vector<boost::shared_ptr<int>> vector_ptr; // 定义标准容器类型
vector_ptr vect(10); // 定义拥有十个元素的容器
// 初始化赋值
int x = 0;
for (auto pos = vect.begin(); pos != vect.end(); ++pos)
{
(*pos) = boost::make_shared<int>(++x); // 工厂函数初始化
cout << "输出值: " << *(*pos) << endl; // 输出数据(两次解引用)
}
// 修改数据
boost::shared_ptr<int> int_ptr = vect[9]; // 获取最后一个数值
*int_ptr = 100; // 修改最后一个数值
cout << "修改后: " << *vect[9] << endl;
// 第二种输出方式(一次解引用完成)
x = 0;
for (auto& ptr : vect)
{
cout << "输出值: " << *ptr << endl;
}
std::system("pause");
return 0;
}
2.5 使用SharedPtr桥接模式
在C++中,shared_ptr有一种常用的设计模式是桥接模式(Bridge Design Pattern)又称为PIMPL
模式。桥接模式的主要作用是将实现细节从类的接口中分离出来,从而使得接口和实现可以独立变化,提高了类的可扩展性和可维护性。
使用shared_ptr
实现桥接模式时,我们可以使用一个基类和多个派生类的继承关系,并使用shared_ptr
来管理对象的生命周期。通过使用shared_ptr
的引用计数技术,可以动态地改变派生类的具体实现,而不会影响到基类接口的实现。其仅对外部暴漏最小的细节,内部类实现用一个shared_ptr
来保存指针。
如下代码所示,首先我们定义MyShared
作为基类,其内部存在一个print
输出函数,而该函数通过boost::shared_ptr<impl> ptr;
指向impl
基址,当输出内容时,自动桥接到impl
派生类上的print
函数上。
#include <iostream>
#include <string>
#include <vector>
#include <boost/smart_ptr.hpp>
using namespace std;
using namespace boost;
// 定义基类
class MyS