12.16 对unique_ptr进行拷贝或赋值,程序会调用删除的函数,标准库为了禁止unique_ptr的拷贝和赋值,将其拷贝构造函数和赋值函数声明为delete的。
12.17 (a) 不合法。unique_ptr需要用指针初始化,int无法转换为指针;(b)合法;(c)合法;(d)合法;(e)合法;(f)合法
12.18 unique_ptr独占对象所有权,无法拷贝和赋值,需要用release操作从一个unique_ptr转移到另一个unique_ptr;shared_ptr共享对象所有权,支持拷贝和赋值,无需release操作。
12.19 将StrBlob和StrBlobPtr定义到头文件StrBlob.h中,代码如下
#ifndef STRBLOB_H
#define STRBLOB_H
#include <string>
#include <vector>
#include <memory>
#include <stdexcept>
using namespace std;
class StrBlobPtr;
class StrBlob {
friend class StrBlobPtr;
public:
typedef vector<string>::size_type size_type;
StrBlob();
StrBlob(initializer_list<string> il);
bool empty() const { return data->empty(); }
size_type size() const { return data->size(); }
void push_back(const string &s) { data->push_back(s); }
void pop_back();
string& front();
const string& front() const;
string& back();
const string& back() const;
StrBlobPtr begin();
StrBlobPtr end();
private:
shared_ptr<vector<string>> data;
void check(size_type i, const string &msg) const;
};
class StrBlobPtr {
friend bool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs);
public:
StrBlobPtr(): curr(0) { }
StrBlobPtr(StrBlob &a, size_t sz = 0):
wptr(a.data), curr(sz) { }
string& deref() const;
StrBlobPtr& incr();
private:
shared_ptr<vector<string>> check(size_t, const string&) const;
weak_ptr<vector<string>> wptr;
size_t curr;
};
void
StrBlob::check(size_type i, const string &msg) const
{
if (data->size() <= i)
throw out_of_range(msg);
}
StrBlob::StrBlob(): data(make_shared<vector<string>>()) { }
StrBlob::StrBlob(initializer_list<string> il): data(make_shared<vector<string>>(il)) { }
void
StrBlob::pop_back()
{
check(0, "pop back on empty StrBlob");
data->pop_back();
}
string&
StrBlob::front()
{
check(0, "front on empty StrBlob");
return data->front();
}
const string&
StrBlob::front() const
{
check(0, "front on empty StrBlob");
return data->front();
}
string&
StrBlob::back()
{
check(0, "back on empty StrBlob");
return data->back();
}
const string&
StrBlob::back() const
{
check(0, "back on empty StrBlob");
return data->back();
}
StrBlobPtr
StrBlob::begin()
{
return StrBlobPtr(*this);
}
StrBlobPtr
StrBlob::end()
{
auto ret = StrBlobPtr(*this, data->size());
return ret;
}
shared_ptr<vector<string>>
StrBlobPtr::check(size_t i, const string &msg) const
{
auto ret = wptr.lock();
if (!ret)
throw runtime_error("unbound StrBlobPtr");
if ( i >= ret->size() )
throw out_of_range(msg);
return ret;
}
string&
StrBlobPtr::deref() const
{
auto p = check(curr, "dereference past end");
return (*p)[curr];
}
StrBlobPtr&
StrBlobPtr::incr()
{
check(curr, "increment past end of StrBlobPtr");
++curr;
return *this;
}
inline
bool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
shared_ptr<vector<string>> l = lhs.wptr.lock(), r = rhs.wptr.lock();
if (l == r)
return (!r || lhs.curr == rhs.curr);
else
return false;
}
inline
bool neq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
return !eq(lhs, rhs);
}
#endif
12.20 使用StrBlob.h进行测试,代码如下
#include <iostream>
#include <fstream>
#include "StrBlob.h"
using namespace std;
int main(int argc, char *argv[])
{
ifstream in(argv[1]);
string line;
StrBlob sblob;
while (getline(in, line)) {
sblob.push_back(line);
}
StrBlobPtr sptr(sblob);
for (sptr = sblob.begin(); neq(sptr, sblob.end()); sptr.incr())
cout << sptr.deref() << endl;
return 0;
}
12.21 使用如下定义可读性更好:
auto p = check(curr, "dereference past end");
return (*p)[curr];
12.22 StrBlob.h修改如下
#ifndef STRBLOB_H
#define STRBLOB_H
#include <string>
#include <vector>
#include <memory>
#include <stdexcept>
using namespace std;
class ConstStrBlobPtr;
class StrBlob {
friend class ConstStrBlobPtr;
public:
typedef vector<string>::size_type size_type;
StrBlob();
StrBlob(initializer_list<string> il);
bool empty() const { return data->empty(); }
size_type size() const { return data->size(); }
void push_back(const string &s) { data->push_back(s); }
void pop_back();
string& front();
const string& front() const;
string& back();
const string& back() const;
ConstStrBlobPtr begin() const;
ConstStrBlobPtr end() const;
private:
shared_ptr<vector<string>> data;
void check(size_type i, const string &msg) const;
};
class ConstStrBlobPtr {
friend bool eq(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs);
public:
ConstStrBlobPtr(): curr(0) { }
ConstStrBlobPtr(const StrBlob &a, size_t sz = 0):
wptr(a.data), curr(sz) { }
string& deref() const;
ConstStrBlobPtr& incr();
private:
shared_ptr<vector<string>> check(size_t, const string&) const;
weak_ptr<vector<string>> wptr;
size_t curr;
};
void
StrBlob::check(size_type i, const string &msg) const
{
if (data->size() <= i)
throw out_of_range(msg);
}
StrBlob::StrBlob(): data(make_shared<vector<string>>()) { }
StrBlob::StrBlob(initializer_list<string> il): data(make_shared<vector<string>>(il)) { }
void
StrBlob::pop_back()
{
check(0, "pop back on empty StrBlob");
data->pop_back();
}
string&
StrBlob::front()
{
check(0, "front on empty StrBlob");
return data->front();
}
const string&
StrBlob::front() const
{
check(0, "front on empty StrBlob");
return data->front();
}
string&
StrBlob::back()
{
check(0, "back on empty StrBlob");
return data->back();
}
const string&
StrBlob::back() const
{
check(0, "back on empty StrBlob");
return data->back();
}
ConstStrBlobPtr
StrBlob::begin() const
{
return ConstStrBlobPtr(*this);
}
ConstStrBlobPtr
StrBlob::end() const
{
auto ret = ConstStrBlobPtr(*this, data->size());
return ret;
}
shared_ptr<vector<string>>
ConstStrBlobPtr::check(size_t i, const string &msg) const
{
auto ret = wptr.lock();
if (!ret)
throw runtime_error("unbound StrBlobPtr");
if ( i >= ret->size() )
throw out_of_range(msg);
return ret;
}
string&
ConstStrBlobPtr::deref() const
{
auto p = check(curr, "dereference past end");
return (*p)[curr];
}
ConstStrBlobPtr&
ConstStrBlobPtr::incr()
{
check(curr, "increment past end of StrBlobPtr");
++curr;
return *this;
}
inline
bool eq(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)
{
shared_ptr<vector<string>> l = lhs.wptr.lock(), r = rhs.wptr.lock();
if (l == r)
return (!r || lhs.curr == rhs.curr);
else
return false;
}
inline
bool neq(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)
{
return !eq(lhs, rhs);
}
#endif
这篇博客探讨了C++ Primer第五版中关于unique_ptr的部分,强调了unique_ptr的不可拷贝和不可赋值特性,解释了为何这样设计以及在实际使用中如何进行对象所有权的转移。同时,通过举例说明了unique_ptr和shared_ptr在所有权管理上的区别。此外,还介绍了如何在StrBlob和StrBlobPtr的实现中应用unique_ptr。

4669

被折叠的 条评论
为什么被折叠?



