《C++ Primer Plus(第六版)》(23)(第十二章 类和动态内存分配 复习题和答案)
学习到这里,C++可以说,已经进入一个既是基础的地方,也是高深的地方。
可能你做了几年开发,都没有接触到这些东西,但是又在潜移默化地使用着。
从现在开始,所有题目都打出来。方便查看了。
12.9 复习题
1.假设String类有如下私有成员:
class String { private: char * str; int len; };a.下述默认构造函数有什么问题?
String::String(){}
str没有获得内存,len也没有初始化。所有的都是不确定的。str应该设置为NULL,或者用new[]初始化,len设置相应的值。
b.下述构造函数有什么问题?
String::String(const char * s) { str = s; len = strlen(s); }
这个只是把s指向的地址放到str。它们是指向同一个内存。如果s被释放了,就出错了。应该使用new[]和strcpy().
c.下述构造函数有什么问题?
String::String(const char* s) { strcpy(str, s); len = strlen(s); }
str没有分配到内存,应该使用new char[len + 1]来分配适当的内存。
2.如果您定义了一个类,其指针成员是使用new初始化的,请指出可能出现的3个问题以及如何纠正这些问题。
a.析构函数没有对指针成员指向的内存进行释放
在析构函数里delete
b.复制或者赋值的时候,直接复制地址,没有进行深度复制。这样可能导致在析构函数释放的时候产生二次释放。
复制的时候要new新的内存,释放旧的内存,定义一个复制构造函数,重载赋值运算符。
c.delete和new不对应
使用new,就要在析构时候使用delete,使用new[],则在析构时候使用delete[]。
3.如果没有显式提供类方法,编译器将自动生成哪些类方法?请描述这些隐式生成函数的行为。
假如类名是ClassName:
ClassName(); 默认构造函数,如果没有构造函数的时候就会自动生成这个,里面不完成任何工作
ClassName(const ClassName&); 复制构造函数,浅复制
ClassName operator=(const ClassName&); 赋值函数,浅复制
~ClassName(); 析构函数,不做任何工作。
没有定义地址运算符,将提供地址运算符。返回对象地址,跟this指针的值一样。
4.找出并改正下述类声明中的错误:
class nifty { char personality[]; int talents; nifty(); nifty(char * s); ostream & operator<<(ostream& os, nifty& n); }; nifty:nifty() { personality = NULL; talents = 0; } nifty:nifty(char* s) { personality = new char[strlen(s)]; personality = s; talents = 0; } ostream & nifty:operator<<(ostream& os, nifty& n) { os << n; }这个代码一堆错误,真的无语。几乎要重写的。
class nifty { private: char personality[40]; int talents; public: nifty(); nifty(const char * s); friend ostream & operator<<(ostream& os, const nifty& n); }; nifty::nifty() { personality[0] = '\0'; talents = 0; } nifty::nifty(const char* s) { strcpy(personality, s); talents = 0; } ostream & operator<<(ostream& os, const nifty& n) { os << n.personality << ":" << n.talents; return os; }
class Golfer { private: char* fullname; int games; int * scores; public: Golfer(); Golfer(const char * name, int g = 0); Golfer(const Golfer& g); ~Golfer(); };
Golfer nancy;//#1 Golfer() Golfer lulu("Little Lulu");//#2 Golfer(const char* name, int g) Golfer roy("Roy Hobbs", 12);//#3 Golfer(const char* name, int g) Golfer * par = new Golfer;//#4 Golfer() Golfer next = lulu;//#5 Golfer(const Golfer& g) Golfer hazzard = "Weed Thwacker";//#6 Golfer(const char* name, int g) *par = nancy;//#7 默认的赋值运算符 nancy = "Nancy Putter";//#8 Golfer(const char* name, int g),然后使用默认的赋值运算符
b.很明显,类需要有另外几个方法才能更有用,但是类需要哪些方法才能防止数据被损坏呢?
一个可以进行深度复制的赋值运算符。