C++Primer 第十二章 动态内存 习题答案

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值