12.1
b1由四个元素:a,an,the,about
b2被销毁
12.2
#pragma once
#include<string>
#include<vector>
#include<list>
#include<stdexcept>
class StrBlob
{
public:
typedef std::vector<std::string>::size_type size_type;
StrBlob();
StrBlob(std::initializer_list<std::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_ptr<std::vector<std::string>> data;
void check(size_type i,const std::string &msg) const;
};
void StrBlob::check(size_type i, const std::string &msg) const
{
if (i >= data->size())
throw std::out_of_range(msg);
}
std::string& StrBlob::front()
{
check(0, "front on empty StrBlob");
return data->front();
}
std::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();
}
12.3
不需要,合法但是没有必要。
12.4
std::vectorstd::string::size_type size_type是一个无符号整型数,是大于等于0的。
12.5
使用explicit
优点:明确参数类型
缺点:不易调试,需要显式转换。
12.6
#include<vector>
#include<iostream>
std::vector<int>* createV()
{
return new std::vector<int>;
}
void readNum(std::vector<int>* p)
{
int tem;
while (std::cin >> tem)
p->push_back(tem);
}
void printVec(std::vector<int>* p)
{
for (auto &i : *p)
std::cout << i << " ";
std::cout<<std::endl;
}
int main()
{
auto p = createV();
readNum(p);
printVec(p);
delete p;
p = nullptr;
return 0;
}
12.7
#include<vector>
#include<iostream>
#include "memory.h"
std::shared_ptr<std::vector<int>> createV()
{
return std::make_shared<std::vector<int>>();
}
void readNum(std::shared_ptr<std::vector<int>> p)
{
int tem;
while (std::cin >> tem)
p->push_back(tem);
}
void printVec(std::shared_ptr<std::vector<int>> p)
{
for (auto &i : *p)
std::cout << i << " ";
std::cout<<std::endl;
}
int main()
{
auto p = createV();
readNum(p);
printVec(p);
return 0;
}
12.8
对于内置类型,默认初始化的对象的值是未定义的。
同时new的内存没有被释放掉。
12.9
对前面部分,r指向的42的内存空间没有被释放掉,
后面部分,正常,r2指向的42被自动释放。
12.10
正确。
12.11
将另一个只能指针也绑定到get返回的指针上是错误的。p的内存被释放掉,再次调用p会报错。
12.12
(a)合法,调用sp并且结束后释放掉它的内存。
(b)不合法,无法将int转换为make_shared型
©不合法,无法将int转换为make_shared型
(d)合法,内存会被释放掉。
12.13
同一内存释放两次,所以不能删除get返回的指针。
12.14
#include<vector>
#include<string>
#include<iostream>
#include "memory.h"
class destination
{
public:
std::string des;
destination(std::string des_) :des(des_){}
};
class connection
{
public:
std::string conn;
connection(std::string conn_):conn(conn_){}
};
connection connect(destination* des_)
{
std::cout << "connect to" << des_->des << std::endl;
return connection(des_->des);
}
void disconnect(connection conn_)
{
std::cout << "disconnect:" << conn_.conn << std::endl;
}
void end_connection(connection *p)
{
disconnect(*p);
}
void f(destination &d)
{
connection c = connect(&d);
std::shared_ptr<connection> p(&c, end_connection);
std::cout << "connecting now(" << p.use_count() << ")" << std::endl;
}
int main()
{
destination des("123");
f(des);
return 0;
}
12.15
#include<vector>
#include<string>
#include<iostream>
#include "memory.h"
class destination
{
public:
std::string des;
destination(std::string des_) :des(des_){}
};
class connection
{
public:
std::string conn;
connection(std::string conn_):conn(conn_){}
};
connection connect(destination* des_)
{
std::cout << "connect to" << des_->des << std::endl;
return connection(des_->des);
}
void f(destination &d)
{
connection c = connect(&d);
std::shared_ptr<connection> p(&c,
[](connection *conn_) {std::cout << "disconnect:" << conn_->conn << std::endl; });
std::cout << "connecting now(" << p.use_count() << ")" << std::endl;
}
int main()
{
destination des("123");
f(des);
return 0;
}
12.16
std::unique_ptr<std::string> p1;
std::unique_ptr<std::string> p2(p1);
/*错误(活动) E1776 无法引用 函数
"std::unique_ptr<_Ty, _Dx>::unique_ptr(const std::unique_ptr<_Ty, _Dx> &)
[其中 _Ty=std::string, _Dx=std::default_delete<std::string>]"
-- 它是已删除的函数
*/
std::unique_ptr<std::string> p1;
std::unique_ptr<std::string> p2;
p2 = p1;
/*严重性 代码 说明 项目 文件 行 禁止显示状态 错误(活动)
E1776 无法引用 函数
"std::unique_ptr<_Ty, _Dx>::operator=(const std::unique_ptr<_Ty, _Dx> &)
[其中 _Ty=std::string, _Dx=std::default_delete<std::string>]"
-- 它是已删除的函数
*/
12.17
(a)初始化错误,参数类型不匹配
(b)编译时合法,pi不是new出来的,因此销毁时使用默认delete会出错。
©合法
(d)编译时合法,ix不是new出来的,因此销毁时使用默认delete会出错。
(e)合法
(f)错误,某个时刻只能有一个unique_ptr指向一个给定对象。
12.18
因为某个时刻多个shared_ptr可以指向同一个给定对象,不需要release。
12.19
#pragma once
#include <string>
#include <initializer_list>
#include <memory>
#include <vector>
#include <stdexcept>
class StrBlobPtr;
class StrBlob
{
public:
friend class StrBlobPtr;
typedef std::vector<std::string>::size_type size_type;
StrBlob();
StrBlob(std::initializer_list<std::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();
const std::string& front() const;
const std::string& back() const;
StrBlobPtr begin();
StrBlobPtr end();
private:
std::shared_ptr<std::vector<std::string>> data;
void check(size_type i, const std::string &msg) const;
};
class StrBlobPtr
{
public:
StrBlobPtr() : curr(0) {};
StrBlobPtr(StrBlob &a, size_t sz = 0) : wptr(a.data), curr(sz) {}
std::string& deref() const;
StrBlobPtr& incr();
private:
std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string&) const;
std::weak_ptr<std::vector<std::string>> wptr;
std::size_t curr;
};
std::shared_ptr<std::vector<std::string>> StrBlobPtr::check(std::size_t i, const std::string &msg) const
{
auto ret = wptr.lock();
if (!ret)
throw std::runtime_error("unbound StrBlobPtr");
if (i >= ret->size())
throw std::out_of_range(msg);
return ret;
}
std::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;
}
StrBlob::StrBlob() : data(std::make_shared<std::vector<std::string>>()) {}
StrBlob::StrBlob(std::initializer_list<std::string> il) : data(std::make_shared<std::vector<std::string>>(il)) {}
void StrBlob::check(size_type i, const std::string &msg) const
{
if (i >= data->size())
throw std::out_of_range(msg);
}
std::string & StrBlob::front()
{
check(0, "front on empty StrBlob");
return data->front();
}
std::string & StrBlob::back()
{
check(0, "back on empty StrBlob");
return data->back();
}
const std::string& StrBlob::front() const
{
check(0, "front on empty StrBlob");
return data->front();
}
const std::string& StrBlob::back() const
{
check(0, "back on empty StrBlob");
return data->back();
}
void StrBlob::pop_back()
{
check(0, "pop_back on empty StrBlob");
data->pop_back();
}
StrBlobPtr StrBlob::begin() { return StrBlobPtr(*this); }
StrBlobPtr StrBlob::end()
{
auto ret = StrBlobPtr(*this, data->size());
return ret;
}
12.20
#include"StrBlob.h"
#include<iostream>
int main()
{
StrBlob b1 = { };
std::string s;
while (getline(std::cin, s))
{
b1.push_back(s);
}
StrBlobPtr p1(b1);
for (auto i = 0; i != b1.size(); ++i)
{
std::cout << p1.deref() << std::endl;
p1.incr();
}
return 0;
}
12.21
前面的版本更好,后一个可读性太差。
12.22
构造函数加个const
12.23
#include<iostream>
#include<string>
#include<memory>
int main()
{
/*char a[] = "aaa";
char b[] = "vvv";
char* sum = new char[strlen("aaa""bbb")+1];
strcat(sum, a);
strcat(sum, b);
std::cout << sum << std::endl;
delete[]sum;*/
std::string s1 = "aaa";
std::string s2 = "bbb";
std::string* sum2 = new std::string;
*sum2 = s1 + s2;
std::cout << *sum2 << std::endl;
delete sum2;
return 0;
}
12.24
#include <iostream>
int main()
{
// need to tell the size.
std::cout << "How long do you want the string? ";
int size{ 0 };
std::cin >> size;
char* input = new char[size + 1]();
std::cin.ignore();
std::cout << "input the string: ";
std::cin.get(input, size + 1);
std::cout << input;
delete[] input;
return 0;
}
12.25
delete []pa;
12.26
#include<iostream>
#include<string>
#include<memory>
int main()
{
std::allocator<std::string> alloc;
auto const p = alloc.allocate(5);
auto q = p;
alloc.construct(q++);
alloc.construct(q++, 10, 'c');
alloc.construct(q++, "hi");
while (q != p)
{
std::cout << *(--q) << std::endl;
alloc.destroy(q);
}
alloc.deallocate(p, 5);
return 0;
}
12.27&12.28&12.30
#pragma once
#include<fstream>
#include<iostream>
#include<sstream>
#include<vector>
#include<memory>
#include<string>
#include<map>
#include<set>
#include<algorithm>
class QueryResult;
class TextQuery
{
public:
using size_type = std::vector<std::string>::size_type;
TextQuery(std::ifstream&);
QueryResult query(const std::string&)const;
private:
std::shared_ptr<std::vector<std::string>> file;
std::map<std::string, std::shared_ptr<std::set<size_type>>> wm;
};
class QueryResult
{
friend std::ostream& print(std::ostream&, const QueryResult&);
public:
QueryResult(std::string s, std::shared_ptr<std::set<TextQuery::size_type>> p,
std::shared_ptr<std::vector<std::string>> f) : sought(s), lines(p), file(f) { }
private:
std::string sought;
std::shared_ptr<std::set<TextQuery::size_type>> lines;
std::shared_ptr<std::vector<std::string>> file;
};
TextQuery::TextQuery(std::ifstream&ifs) :file(new std::vector<std::string>)
{
std::string text;
while (getline(ifs, text))
{
file->push_back(text);
int n = file->size() - 1;
std::istringstream line(text);
std::string text;
while (line >> text)
{
std::string word;
std::copy_if(text.begin(), text.end(), std::back_inserter(word), isalpha);
auto &lines = wm[word];
if (!lines)
lines.reset(new std::set<size_type>);
lines->insert(n);
}
}
}
QueryResult TextQuery::query(const std::string &sought) const
{
static std::shared_ptr<std::set<TextQuery::size_type>> nodata(new std::set<TextQuery::size_type>);
auto loc = wm.find(sought);
if (loc == wm.end())
return QueryResult(sought, nodata, file);
else
return QueryResult(sought, loc->second, file);
}
std::ostream &print(std::ostream &os, const QueryResult &qr)
{
os << qr.sought << " occurs " << qr.lines->size() << " " /*<< make_plural(qr.lines->size(), "time", "s")*/ << std::endl;
for (auto num : *qr.lines)
os << "\t(line " << num + 1 << ") " << *(qr.file->begin() + num) << std::endl;
return os;
}
//main
#include <iostream>
#include <string>
#include "TextQuery.h"
void runQueries(std::ifstream &infile)
{
TextQuery tq(infile);
while (true) {
std::cout << "enter word to look for, or q to quit: ";
std::string s;
if (!(std::cin >> s) || s == "q") break;
print(std::cout, tq.query(s)) << std::endl;
}
}
int main()
{
std::ifstream file("data.txt");
runQueries(file);
}
12.29
while,更简单。
12.31
vector是顺序容器,set是关联容器。
vector不能保证只有一个行号。
12.32
#ifndef TEXTQUERY_H_
#define TEXTQUERY_H_
#include <string>
#include <vector>
#include <map>
#include <fstream>
#include <sstream>
#include <set>
#include <memory>
#include <iostream>
#include <algorithm>
#include <iterator>
#include "StrBlob_ex22.h"
class QueryResult;
class TextQuery
{
public:
using line_no = std::vector<std::string>::size_type;
TextQuery(std::ifstream&);
QueryResult query(const std::string&) const;
private:
StrBlob file;
std::map<std::string, std::shared_ptr<std::set<line_no>>> wm;
};
class QueryResult
{
friend std::ostream& print(std::ostream&, const QueryResult&);
public:
QueryResult(std::string s, std::shared_ptr<std::set<TextQuery::line_no>> p, StrBlob f) : sought(s), lines(p), file(f) { }
private:
std::string sought;
std::shared_ptr<std::set<TextQuery::line_no>> lines;
StrBlob file;
};
TextQuery::TextQuery(std::ifstream &ifs){
std::string text;
while(std::getline(ifs, text))
{
file.push_back(text);
int n = file.size() - 1;
std::istringstream line(text);
std::string text;
while(line >> text)
{
std::string word;
std::copy_if(text.begin(), text.end(), std::back_inserter(word), isalpha);
// std::cout << word << std::endl;
auto &lines = wm[word];
if(!lines)
lines.reset(new std::set<line_no>);
lines->insert(n);
}
}
}
QueryResult TextQuery::query(const std::string &sought) const
{
static std::shared_ptr<std::set<TextQuery::line_no>> nodata(new std::set<TextQuery::line_no>);
auto loc = wm.find(sought);
if(loc == wm.end())
return QueryResult(sought, nodata, file);
else
return QueryResult(sought, loc->second, file);
}
std::ostream &print(std::ostream &os, const QueryResult &qr)
{
os << qr.sought << " occurs " << qr.lines->size() << " " /*<< make_plural(qr.lines->size(), "time", "s")*/ << std::endl;
for(auto num : *qr.lines)
{
ConstStrBlobPtr p(qr.file, num);
os << "\t(line " << num + 1 << ") " << p.deref() << std::endl;
}
return os;
}
#endif
12.33
#ifndef TEXTQUERY_H_
#define TEXTQUERY_H_
#include <string>
#include <vector>
#include <map>
#include <fstream>
#include <sstream>
#include <set>
#include <memory>
#include <iostream>
#include <algorithm>
#include <iterator>
#include "StrBlob_ex22.h"
class QueryResult;
class TextQuery
{
public:
using line_no = std::vector<std::string>::size_type;
TextQuery(std::ifstream&);
QueryResult query(const std::string&) const;
private:
StrBlob file;
std::map<std::string, std::shared_ptr<std::set<line_no>>> wm;
};
class QueryResult
{
friend std::ostream& print(std::ostream&, const QueryResult&);
public:
QueryResult(std::string s, std::shared_ptr<std::set<TextQuery::line_no>> p, StrBlob f) : sought(s), lines(p), file(f) { }
std::set<StrBlob::size_type>::iterator begin() const { return lines->begin(); }
std::set<StrBlob::size_type>::iterator end() const { return lines->end(); }
shared_ptr<StrBlob> get_file() const { return std::make_shared<StrBlob>(file); }
private:
std::string sought;
std::shared_ptr<std::set<TextQuery::line_no>> lines;
StrBlob file;
};
TextQuery::TextQuery(std::ifstream &ifs){
std::string text;
while(std::getline(ifs, text))
{
file.push_back(text);
int n = file.size() - 1;
std::istringstream line(text);
std::string text;
while(line >> text)
{
std::string word;
std::copy_if(text.begin(), text.end(), std::back_inserter(word), isalpha);
// std::cout << word << std::endl;
auto &lines = wm[word];
if(!lines)
lines.reset(new std::set<line_no>);
lines->insert(n);
}
}
}
QueryResult TextQuery::query(const std::string &sought) const
{
static std::shared_ptr<std::set<TextQuery::line_no>> nodata(new std::set<TextQuery::line_no>);
auto loc = wm.find(sought);
if(loc == wm.end())
return QueryResult(sought, nodata, file);
else
return QueryResult(sought, loc->second, file);
}
std::ostream &print(std::ostream &os, const QueryResult &qr)
{
os << qr.sought << " occurs " << qr.lines->size() << " " /*<< make_plural(qr.lines->size(), "time", "s")*/ << std::endl;
for(auto num : *qr.lines)
{
ConstStrBlobPtr p(qr.file, num);
os << "\t(line " << num + 1 << ") " << p.deref() << std::endl;
}
return os;
}
#endif