栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

c++Primer第12章:动态内存与智能指针

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

c++Primer第12章:动态内存与智能指针

12.1.1节练习

12.1:在此代码的结尾,b1和b2各包含多少个元素?

StrBlob b1;
{
	StrBolb b2={"a","b","the"};
	b1=b2;
	b2.push_back("about");
}

答:考虑到是智能指针,所以会共享内存,所以都是4个
12.2:编写你自己的StrBlob类,包含const版本的front和back
答:

class StrBlob {
public :
	typedef std::vector::size_type size_type;
	StrBlob();
	StrBlob(std::initializer_list i1);
	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() const {
		return data->front();
	}
	std::string& back() const {
		return data->back();
	}
private:
	std::shared_ptr>data;
	void check(size_type i, const std::string& msg) const;

};

12.3:StrBlob需要const版本的push_back和pop_back吗?如果需要,添加进去,否则给出理由
答:不需要,常量对象不允许修改共享对象内容
12.4:在我们的check函数中,没有检查i是否大于0,为什么可以忽略这个检查?
答:因为很容易保证传给它的i值符合要求
12.5:我们未编写接受一个initializer_list explist,参数的构造函数。讨论这个设计的优点和缺点
答:略

12.1.2节练习

12.6:编写函数,返回一个动态分配的int的vector传递给另一个函数,这个函数读取标准输入,将读取的值保存在vector中。再将vector传递给另一个函数,打印读入的值。记得在恰当的时刻delete vector
答:

vector* new_vector(void){
	return new vector;
}
void read_ints(vector*pr) {
	int v;
	while (cin >> v) {
		pr->push_back(v);
	}
}
void print_ints(vector* pv) {
	for (const auto& v : *pv) {
		cout << v << " ";
	}
	cout << endl;
}
int main() {
	vector* pv = new_vector();
	if (!pv) {
		cout << " 内存不足" << endl;
		return -1;
	}
	read_ints(pv);
	print_ints(pv);
	delete pv;
	return 0;
	
	return 0;
}

12.7:重做上一题,这次使用shared_ptr而不是内置指针
答:

shared_ptr>new_vector(void){
	return make_shared>();	
}
void read_ints(shared_ptr>pr) {
	int v;
	while (cin >> v) {
		pr->push_back(v);
	}
}
void print_ints(shared_ptr>pv) {
	for (const auto& v : *pv) {
		cout << v << " ";
	}
	cout << endl;
}
int main() {
	shared_ptr>pv = new_vector();
	if (!pv) {
		cout << " 内存不足" << endl;
		return -1;
	}
	read_ints(pv);
	print_ints(pv);
	cout << pv.unique();
	return 0;
	
	return 0;
}

12.8:下面的函数是否有错误?如果有解释原因

bool b(){
int *p=new int;
//...
return p;
}

答:没有,因为可以进行强制转换,但是做法不太好
12.9:解释下面代码执行结果

int *q=new int(42),*r=new int(100);
r=q;
auto q2=make_shared(42);
r2=make_shared(1000);
r2=q2;

答:如果是用new 的话,会有无用的内存无法释放,而智能指针则会自动释放

12.1.3节练习

12.10:下面的代码调用了413页中定义的process函数,解释此函数调用是否正确?

shared_ptrp(new int(42));
process(shared_ptrp());

答:调用正确
12.11:如果我们像下面这样调用process,会发生什么

process(shared_ptr(p.get()));

答:发生了错误,应该是造成了空悬指针
12.12:p和sp的定义如下,对于接下来的对process的每个调用,如果合法,解释它做了什么,如果不合法,解释错误原因

auto p=new int();
auto sp=make_shared();
(a)process(sp);
(b)process(new int());
(c)process(p)
(d)process(shared_ptr(p));

答:a合法,b合法,c不合法,d合法,但会造成空悬指针
12.13:如果执行下面的代码,会发生什么

auto sp=make_shared();
auto p=sp.get();
delete p;

答:智能指针还在,结果内存就释放了,应该会报错

12.1.4

12.14:编写你自己版本用的shared_ptr管理的connection函数
答:

struct destination {};
struct connection {};
connection connect(destination* pd) {
	cout << " 打开连接" << endl;
	return connection();
}
void disconnection(connection c) {
	cout << "关闭连接" << endl;
}
void f(destination& d) {
	cout << "直接管理connection" <p(&c, end_connection);
	cout << endl;
}

12.15:重写上一题的程序,用lambda代替end_connection
答:

[](connection*p)->void{ disconnection(*p); }
用这个换入即可
12.1.5节练习

12.16:如果你试图拷贝或赋值unique_ptr,编译器并不是总能给出易于理解的错误信息。编写包含这样的错误的程序,观察编译器如恶化诊断这种错误
答:自己可以试一下
12.17:下面的unique_ptr声明中,哪些是合法的,哪些可能导致后续的程序错误?解释每个错误的问题在哪里

int ix=1024,*pi=&ix,*pi2=new int(2048);
typedef unique_ptrIntP;
(a)IntP p0(ix)//错误,需要指针初始化
(b)IntP p1(pi)//合法,但是释放内存后,ix会成为空悬指针
(c)IntP p2(pi2)//合法,利用动态分配对象的指针来初始化是正确的
(d)IntP p3(&ix)//合法
(e)IntP p4(new int(2048))//合法
(f)IntP p5(p2.get())//合法,但是会产生空悬指针

12.18:shared_ptr为什么没有release成员
答:可以共享内存,不需要

12.1.6节练习

12.19:定义你自己的StrBlobPtr,更新StrBlob类,加入恰当的friend声明和begin()以及end()成员
答:

//全是参考答案的
main.c
#include
using namespace std;
#include "my_StrBlob.h"
int main() {
	StrBlob b1;
	{
		StrBlob b2 = { "a","an","end" };
		b1 = b2;
		b2.push_back("about");
		cout << b2.size() << endl;
	}
	cout << b1.size() << endl;
	cout << b1.front() << " " << b1.back() << endl;
	const StrBlob b2 = b1;
	const StrBlob b3 = b1;
	cout << b3.front() << " " << b3.back() << endl;
	for (auto it = b1.begin();neq(it, b1.end());it.incr())
		cout << it.deref() << endl;
	return 0;
}
my_StrBlob.h
#ifndef MY_STRBLOB_H
#define MY_STRBLOB_H
#include
#include
#include
#include
#include
using namespace std;
class StrBlobPtr;

class StrBlob {
	friend class StrBlobPtr;
public:
	typedef vector::size_type size_type;
	StrBlob();
	StrBlob(initializer_listi1);
	size_type size() const { return data->size(); };
	bool empty() const { return data->empty(); };
	//添加和删除元素
	void push_back(const string& t) { data->push_back(t); };
	void pop_back();
	//元素访问
	string& front();
	const string& front() const;
	string& back();
	const string& back() const;
	
	//提供给StrBlob的接口
	StrBlobPtr begin();
	StrBlobPtr end();
private:
	shared_ptr>data;
	//如果data[i]不合法,抛出一个异常
	void check(size_type i, const std::string& msg) const;

};
inline StrBlob::StrBlob() :data(make_shared>()) {};
StrBlob::StrBlob(initializer_listi1) :data(make_shared>(i1)) {};
inline void StrBlob::check(size_type i, const string& msg) const {
	if (i >= data->size())
		throw out_of_range(msg);
}
inline string& StrBlob::front() {
	check(0, "front on empty StrBlob");
	return data->front();
}
inline const string& StrBlob::front() const {
	check(0, "front on empty StrBlob");
	return data->front();
}
inline string& StrBlob::back() {
	check(0, "back on empty StrBlob");
	return data->back();
}
inline const string& StrBlob::back()const {
	check(0, "back on empty StrBlob");
	return data->back();
}
inline void StrBlob::pop_back() {
	check(0, "pop_back on empty StrBlob");
	data->pop_back();
}
//当试图访问一个不存在的元素时,StrBlobPtr抛出一个异常
class StrBlobPtr {
	friend bool eq(const StrBlobPtr&, const StrBlobPtr&);
public :
	StrBlobPtr() :curr(0) {}
	StrBlobPtr(StrBlob& a, size_t sz = 0) :wptr(a.data), curr(sz) {};
	string& deref() const;
	StrBlobPtr& incr();
	StrBlobPtr& decr();
private:
	shared_ptr>check(size_t, const string&) const;
	weak_ptr>wptr;
	size_t curr;
};
inline shared_ptr>StrBlobPtr::check(size_t i, const string& msg)const {
	auto ret = wptr.lock();
	if (!ret) {
		throw runtime_error("enbound StrBlobPtr");
	}
	if (i >= ret->size())
		throw out_of_range(msg);
	return ret;
}
inline string& StrBlobPtr::deref() const {
	auto p = check(curr, "derefrence past end");
	return (*p)[curr];
}
//前缀递增,返回递增后的对象的引用
inline StrBlobPtr& StrBlobPtr::incr() {
	check(0, "increment past end of StrBlobPtr");
	++curr;	
	return *this;
}
//前缀递减
inline StrBlobPtr& StrBlobPtr::decr() {
	--curr;
	check(-1, "decrement past of begin of StrBlobPtr");
	return *this;
}
inline StrBlobPtr StrBlob::begin() {
	return StrBlobPtr(*this);
}
inline StrBlobPtr StrBlob::end() {
	auto ret = StrBlobPtr(*this, data->size());
	return ret;
}
inline bool eq(const StrBlobPtr& lhs, const StrBlobPtr& rhs) {
	auto 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中,用一个StrBlobPtr打印出StrBlob中的每个元素
答:

int main(){
	ifstream in("D:\text.txt");
	StrBlob b;
	string s;
	while(getline(in,s))
	b.push_back();
	for(auto it=b.begin();neq(it,b.end());it.incr())
	cout< 

12.21:略
12.22:略

12.2.1节练习

12.23:编写一个程序,连接两个字符串字面量,将结果保存在一个动态分配的char数组中,连接两个标准string对象
答:

char
 	const char* str1 = "hello";
    const char* str2 = "world";
    auto my_str = new char[40];
    int count = 0;
    for (int i = 0;i < strlen(str1);i++) {
        my_str[count++] = str1[i];
    }
    for (int i = 0;i < strlen(str2);i++) {
        my_str[count++] = str2[i];
    }
    my_str[count] = '';
    cout << my_str << endl;
//string
#include
#include
#include
using namespace std;
int main()
{
    string str1 = "hello";
    string str2 = "world";
    char* my_str = new char[40];
    strcpy(my_str, (str1 + str2).c_str());
    cout << my_str << endl;
    return 0;
}

12.24:编写一个程序,从标准输入中读入一个字符串,存入一个动态分配的字符数数组中。
答:

#include
#include
using namespace std;
int main() {
	string s;
	while (cin >> s) {
		char* str = new char[s.size() + 1];
		strcpy(str, s.c_str());
		cout << str << endl;
	}
}

12.25:给定下面的new表达式,你应该如何释放pa

int*pa=new int[10];

答:delete [] pa

12.2.2节练习

12.26:用allocator重写427页程序
答:

#include
#include
#include
using namespace std;
const int n = 2;
int main() {
	allocatoralloc;
	
	auto const p = alloc.allocate(n);
	string s;
	string* q = p;
	while (cin >> s && q != p + n) {
		alloc.construct(q++, s);
	}
	const size_t size = q - p;
	cout << *p << " "< 
后言 

后几题就不写了,主要都是对所学知识的应用,我实在是不想搞了

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/396337.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号