网站建设费用 无形资产,网站建设衣服,常州网站建设公司如何,深圳龙华区租房使用动态内存的一个常见原因是允许多个对象共享相同的状态。 例如#xff0c;假定我们希望定义一个名为Blob 的类#xff0c;保存一组元素。与容器不同#xff0c;我们希望Blob对象的不同拷贝之间共享相同的元素。即#xff0c;当我们拷贝一个Blob时#xff0c;原Blob对象… 使用动态内存的一个常见原因是允许多个对象共享相同的状态。 例如假定我们希望定义一个名为Blob 的类保存一组元素。与容器不同我们希望Blob对象的不同拷贝之间共享相同的元素。即当我们拷贝一个Blob时原Blob对象及其拷贝应该引用相同的底层元素。现在我们先定义一个管理string的类此版本命名为StrBlob。 定义 StrBlob类
实现一个新的集合类型的最简单方法是使用某个标准库容器来管理元素。采用这种方法我们可以借助标准库类型来管理元素所使用的内存空间。在本例中我们将使用vector来保存元素。
但是我们不能在一个Blob对象内直接保存vector因为一个对象的成员在对象销毁时也会被销毁。例如
假定b1和 b2是两个Blob对象共享相同的vector。如果此vector保存在其中一个Blob中——例如b2中,那么当b2离开作用域时,此vector也将被销毁也就是说其中的元素都将不复存在。为了保证 vector中的元素继续存在我们将vector保存在动态内存中。
为了实现我们所希望的数据共享,我们为每个StrBlob设置一个shared_ptr来管理动态分配的 vector。此 shared_ptr的成员将记录有多少个StrBlob 共享相同的vector并在vector的最后一个使用者被销毁时释放vector。
我们还需要确定这个类应该提供什么操作。当前我们将实现一个vector操作的小的子集。我们会修改访问元素的操作如 front和 back): 在我们的类中如果用户试图访问不存在的元素这些操作会抛出一个异常。
我们的类有一个默认构造函数和一个构造函数接受单一的 initializer_liststring类型参数。此构造函数可以接受一个初始化器的花括号列表。 initializer_list对象中的元素永远是常量值我们无法改变initializer_list对象中元素的值。在进行函数调用的时候需要使用花括号将所有的参数括起来。 class StrBlob{
public:typedef std::vectorstd::string::size_type size_type;StrBlob();StrBlob(std::initializer_liststd::string il);size_type size() const { return data-size(); }bool empty() const { return data-empty(); }//添加和删除元素void push_back(const std::string t){ data-push_back(t); }void pop_back();//元素访问std::string front();std::string back();private:std::shared_ptrstd::vectorstd::string data;//如果data[i]不合法抛出一个异常void check(size_type i, const std::string msg) const;
};在此类中我们实现了size、empty和 push_back成员。这些成员通过指向底层vector的 data成员来完成它们的工作。例如对一个 StrBlob对象调用size()会调用data-size()依此类推。
StrBlob构造函数
两个构造函数都使用初始化列表来初始化其data成员令它指向一个动态分配的vector。默认构造函数分配一个空vector:
StrBlob::StrBlob() : data(make_sharedvectorstring()){ }
StrBlob::StrBlob(initializer_liststring il): data(make_sharedvectorstring(il)) { }接受一个initializer_list的构造函数将其参数传递给对应的vector构造函数。此构造函数通过拷贝列表中的值来初始化vector的元素。
元素访问成员函数
pop_back、front和 back操作访问vector中的元素。这些操作在试图访问元素之前必须检查元素是否存在。由于这些成员函数需要做相同的检查操作我们为StrBlob定义了一个名为check的private工具函数它检查一个给定索引是否在合法范围内。除了索引check还接受一个string参数它会将此参数传递给异常处理程序这个string描述了错误内容:
void StrBlob::check(size_type i, const string msg) const
{if(i data-size())throw out_of_range(msg);
}pop_back和元素访问成员函数首先调用check。如果check成功这些成员函数继续利用底层vector的操作来完成自己的工作:
string StrBlob::front()
{//如果vector为空check会抛出一个异常check(0, front on empty StrBlob);return data-front();
}
string StrBlob::back()
{check(0, back on empty StrBlob);return data-back();
}
void StrBlob::pop_back()
{check(0, pop_back on empty StrBlob);data-pop_back();
}StrBlob 的拷贝、赋值和销毁
StrBlob使用默认版本的拷贝、赋值和销毁成员函数来对此类型的对象进行这些操作。默认情况下这些操作拷贝、赋值和销毁类的数据成员。 我们的StrBlob类只有一个数据成员它是shared_ptr类型。因此当我们拷贝、赋值或销毁一个 StrBlob对象时它的shared_ptr成员会被拷贝、赋值或销毁。
拷贝一个shared_ptr会递增其引用计数;将一个shared_ptr赋予另一个shared_ptr会递增赋值号右侧shared_ptr的引用计数而递减左侧shared_ptr的引用计数。如果一个shared_ptr的引用计数变为0它所指向的对象会被自动销毁。因此对于由 StrBlob构造函数分配的vector当最后一个指向它的StrBlob对象被销毁时它会随之被自动销毁。
注仅供学习参考如有不足欢迎指正