C++Primer第五版 习题答案 第十二章 动态内存(Dynamic Memory)

练习12.1

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

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

b1包含4个元素;
b2被销毁。

练习12.2

编写你自己的StrBlob 类,包含const 版本的 front 和 back。

strblob.h

#ifndef STRBLOB_H_
#define STRBLOB_H_

#include <string>
#include <initializer_list>
#include <memory>
#include <vector>
#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();
	const std::string& front() const;
	const std::string& back() const;
private:
	std::shared_ptr<std::vector<std::string>> data;
	void check(size_type i, const std::string &msg) const;
};

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();
}

#endif

ex02.cpp

#include "StrBlob.h"
#include <iostream>

int main()
{
   
   
	StrBlob b1 = {
   
   "a", "an", "the"};
	const StrBlob b2 = {
   
   "a", "b", "c"};

	std::cout << b1.back() << std::endl;
	std::cout << b2.back() << std::endl;

	return 0;
}

练习12.3

StrBlob 需要const 版本的push_back 和 pop_back吗?如需要,添加进去。否则,解释为什么不需要。

不需要,添加进去虽然编译器不会报错,但是这样不符合类使用者的使用习惯。

练习12.4

在我们的 check 函数中,没有检查 i 是否大于0。为什么可以忽略这个检查?

可以忽略,本身i就是大于0的。

练习12.5

我们未编写接受一个 initializer_list explicit 参数的构造函数。讨论这个设计策略的优点和缺点。

使用explicit之后
优点:我们可以清楚地知道使用的是哪种类型;
缺点:不易使用,需要显示地初始化。

练习12.6

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

#include <string>
#include <iostream>
#include <vector>

std::vector<int> *create_vi()
{
   
   
	return new std::vector<int>;
}

void push_vi(std::vector<int> *p)
{
   
   
	int i;
	while(std::cin >> i)
		p->push_back(i);
}

void print_vi(std::vector<int> *p)
{
   
   
	for(const auto i : (*p))
		std::cout << i << std::endl;
}

int main()
{
   
   
	auto p = create_vi();
	push_vi(p);
	print_vi(p);
	delete p;

	return 0;
}

练习12.7

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

#include <string>
#include <iostream>
#include <vector>
#include <memory>

std::shared_ptr<std::vector<int>> create_vi()
{
   
   
	return std::make_shared<std::vector<int>>();
}

void push_vi(std::shared_ptr<std::vector<int>> p)
{
   
   
	int i;
	while(std::cin >> i)
		p->push_back(i);
}

void print_vi(std::shared_ptr<std::vector<int>> p)
{
   
   
	for(const auto i : (*p))
		std::cout << i << std::endl;
}

int main()
{
   
   
	auto p = create_vi();
	push_vi(p);
	print_vi(p);
	// delete p;

	return 0;
}

练习12.8

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

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

指针p被转换成bool值,new的内存没有被delete,内存没有被释放。

练习12.9

解释下面代码执行的结果。

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

r=q后r所指的内存没有释放,应该先delete r,再r=q;
第二段代码内存会自动释放。

练习12.10

下面的代码调用了第413页中定义的process 函数,解释此调用是否正确。如果不正确,应如何修改?

shared_ptr<int> p(new int(42));
process(shared_ptr<int>(p));

正确。

练习12.11

如果我们像下面这样调用 process,会发生什么?

process(shared_ptr<int>(p.get()));

离开process时,p指向的内存会被释放,再使用p指针时会出现错误。

练习12.12

p 和 sp 的定义如下,对于接下来的对 process 的每个调用,如果合法,解释它做了什么,如果不合法,解释错误原因:

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

(a)合法,将智能指针赋值给process;
(b)不合法,shared_ptr初始化内置指针时需要使用直接初始化的形式;
(c)不合法,shared_ptr初始化内置指针时需要使用直接初始化的形式;
(d)合法。

练习12.13

如果执行下面的代码,会发生什么?

auto sp = make_shared<int>();
auto p = sp.get();
delete p;

sp和p指向的是同一个对象,程序中手动销毁了p所指向的对象,程序结束会自动销毁sp所指向的对象,会销毁两次同一个对象而报错。报错代码如下:

$ ./ex13
double free or corruption (out)
Aborted (core dumped)

练习12.14

编写你自己版本的用 shared_ptr 管理 connection 的函数。

#include <string>
#include <memory>
#include <iostream>

struct destination
{
   
   
    std::string des;
    destination(std::string des_) : des(des_){
   
   }
};

struct connection
{
   
   
    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("aaa");
    f(des);

    return 0;
}

练习12.15

重写第一题的程序,用 lambda 代替end_connection 函数。

#include <string>
#include <memory>
#include <iostream>

struct destination
{
   
   
    std::string des;
    destination(std::string des_) : des(des_){
   
   }
};

struc
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值