16.28 重新定义未SP和UP两个模板:
#ifndef SP_H
#define SP_H
#include <iostream>
using namespace std;
template <typename T>
class SP {
public:
SP(): p(nullptr), use(nullptr) { }
explicit SP(T *pt): p(pt), use(new size_t(1)) { }
SP(const SP &sp): p(sp.p), use(sp.use) { if (use) ++*use; }
SP& operator=(const SP&);
~SP();
T& operator*() { return *p; }
T& operator*() const { return *p; }
private:
T *p;
size_t *use;
};
template <typename T>
SP<T>& SP<T>::operator=(const SP &rhs)
{
if (use) {
--*use;
if (*use == 0) {
delete p;
delete use;
}
}
if (rhs.use)
++*rhs.use;
p = rhs.p;
use = rhs.use;
return *this;
}
template <typename T>
SP<T>::~SP()
{
if (use) {
--*use;
if (*use == 0) {
delete p;
delete use;
}
}
}
template <typename T, class... Args>
SP<T> make_SP(Args&&... args)
{
return SP<T>(new T(std::forward<Args>(args)...));
}
template <typename T>
class UP {
public:
UP(): p(nullptr) { }
UP(const UP &up) = delete;
explicit UP(T* pt) : p(pt) {}
UP& operator=(const UP&) = delete;
~UP();
T* release();
void reset(T *new_p);
T& operator*() { return *p; }
T& operator*() const { return *p; }
private:
T *p;
};
template <typename T>
UP<T>::~UP()
{
if (p)
delete p;
}
template <typename T>
T* UP<T>::release()
{
T *q = p;
p = nullptr;
return q;
}
template <typename T>
void UP<T>::reset(T *new_p)
{
auto temp = new_p;
if (p)
delete p;
p = temp;
}
#endif
16.29 重新修改Blob模板:
#ifndef BLOB_H
#define BLOB_H
#include <iostream>
#include <vector>
#include <stdexcept>
#include <memory>
#include "sp.h"
using namespace std;
template <typename> class BlobPtr;
template <typename T> class Blob {
friend class BlobPtr<T>;
public:
typedef typename vector<T>::size_type size_type;
Blob();
Blob(initializer_list<T> il);
size_type size() const { return (*data).size(); }
bool empty() const { return (*data).empty(); }
void push_back(const T &t) { (*data).push_back(t); }
void push_back(T &&t) { (*data).push_back(std::move(t)); }
void pop_back();
T& front();
T& back();
T& operator[](size_type i);
const T& front() const;
const T& back() const;
const T& at(size_type) const;
const T& operator[](size_type i) const;
private:
SP<vector<T>> data;
void check(size_type i, const string &msg) const;
};
template <typename T>
void Blob<T>::check(size_type i, const string &msg) const
{
if (i >= (*data).size())
throw out_of_range(msg);
}
template <typename T>
Blob<T>::Blob(): data(make_SP<vector<T>>()) { }
template <typename T>
Blob<T>::Blob(initializer_list<T> il):
data(make_SP<vector<T>>(il)) { }
template <typename T>
void Blob<T>::pop_back()
{
check(0, "pop back on empty Blob");
(*data).pop_back();
}
template <typename T>
T& Blob<T>::front()
{
check(0, "front on empty Blob");
return (*data).front();
}
template <typename T>
T& Blob<T>::back()
{
check(0, "back on empty Blob");
return (*data).back();
}
template <typename T>
T& Blob<T>::operator[](size_type i)
{
check(i, "subscritpt out of range");
return (*data)[i];
}
template <typename T>
const T& Blob<T>::front() const
{
check(0, "front on empty Blob");
return (*data).front();
}
template <typename T>
const T& Blob<T>::back() const
{
check(0, "back on empty Blob");
return (*data).back();
}
template <typename T>
const T& Blob<T>::operator[](size_type i) const
{
check(i, "subscritpt out of range");
return (*data)[i];
}
template <typename T>
const T& Blob<T>::at(size_type i) const
{
check(i, "subscritpt out of range");
return (*data).at(i);
}
#endif
16.30 测试主程序:
#include <string>
#include <iostream>
#include <vector>
#include "sp_blob.h"
using namespace std;
int main()
{
Blob<string> b1; // empty Blob
cout << b1.size() << endl;
{ // new scope
Blob<string> b2 = {"a", "an", "the"};
b1 = b2; // b1 and b2 share the same elements
b2.push_back("about");
cout << b1.size() << " " << b2.size() << endl;
} // b2 is destroyed, but the elements it points to must not be destroyed
cout << b1.size() << endl;
for(size_t i = 0; i < b1.size(); ++i)
{
cout << b1.at(i) << " ";
}
cout << endl << endl;
UP<int> u1(new int(42));
cout << *u1 << endl;
UP<int> u2(u1.release());
cout << *u2 << endl;
return 0;
}
16.31 shared_ptr在运行时绑定删除器,unique_ptr在编译时绑定删除器。对unique_ptr而言,删除器类型是unique_ptr类型的一部分。通过这种方式,unique_ptr避免了间接调用删除器的开销,还可以将自定义的删除器(DebugDelete)编译为内联形式。