代码
#include <iostream>
using namespace std;
struct A{
int a;
};
A & clone(A & a) {
A * p;
*p = a;
cout << "p addr" << p << endl;
return *p;
}
int main() {
A a = A{3};
A & r = a;
cout << "r addr" << &r << endl;
A & v = clone(r);
cout << "v addr" << &v << endl;
cout << a.a << " " << v.a << endl;
v.a = 2;
cout << a.a << " " << v.a << endl;
delete &v;
return 0;
}
输出
r addr0x7fff5514c938
p addr0x7fff78e62300
v addr0x7fff78e62300
3 3
3 2
a.out(22733,0x7fff77e0a000) malloc: *** error for object 0x7fff78e62300: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
参考书目: C++ Primer Plus 6th > 8 Adventure in Functions > Reference Variables(page 400 , pdf 中的 415 页)
A call to clone() conceals the call to new, making it simpler to forget to use delete later.
疑问:
- 函数 clone 中是否在堆中新分配了内存给*p
?(个人认为不是,根据地址来看,地址属于栈)
- 为什么书中写到是隐式调用了 new ,但是当 delete 的时候出现pointer being freed was not allocated
的错误?
环境
- mac
- g++
- c++11
1
colatin 2015-11-03 21:53:46 +08:00
建议把 c 的指针学好先。
A *p; *p = a; 这里的 p 就是个野指针。*p=a 相当于在一个不知道什么地方的地方写了一个值。 |
2
superhxnju OP @colatin 大概知道是个野指针,但就是书看到这里的时候很困惑。书里面的这段是我理解有误。。。还是就是有问题?
|
3
Ethaniz 2015-11-03 22:00:41 +08:00
没听说过 clone 会隐式调用 new 呢,你这里的情况是:在 clone 中声明了一个栈变量,类型是个指针,指向地址随机,然后把这个指针指向的地址赋上了 a 的值,然后又返回了这个指针指向的值的引用。函数调用结束,该指针消失。自始至终没有向堆申请任何空间,所以导致 delete 失败。
|
4
theoractice 2015-11-03 22:20:03 +08:00
http://book.douban.com/review/5472087/
这书是瞎写的吧。 Accelerated C++ Effective C++ More Effective C++ www.cplusplus.com/reference/ 看这些足够了。 |
5
superhxnju OP @theoractice 看的是 c++ primer plus ,重拾一下 c++
|
6
superhxnju OP @theoractice 看看基础就行
|
7
znoodl 2015-11-03 22:43:09 +08:00 via iPhone
经典的不是 c++ primer 吗? 不带 plus ,不是一个作者,书里有 delete 的例子吗
|
8
superhxnju OP @znoodl 被名字给欺骗了
|
9
SYP 2015-11-03 23:25:48 +08:00
这样的代码这本书还说的一本正经,还是放弃掉吧。
|
10
yangyanggnu 2015-11-04 09:38:38 +08:00
基本上,这,是作者的疏忽,但不能因此完全否定它的价值。
============================================== ***《 C++ Primer Plus (第 6 版)中文版》 勘误表*** 联系: [email protected] 时间: 2013-9-24 ============================================== P268 错误: free_throws * pt; 修正: free_throws * pt = new free_throws; P291 错误:在这两个模板函数中, recycle<blot *>(blot *) 被认为是更具体的 修正:在这两个模板函数中, recycle<blot>(blot *) 被认为是更具体的 P337 错误: static const LIMIT = 25; 修正: static const unsigned LIMIT = 25; P386 错误: t4 = t1 + t2 + t3 先转换为 t4 = t1.operator+(t2 + t3) 再转换为 t4 = t1.operator+(t2.operator+(t3)) 修正: t4 = t1 + t2 + t3 先转换为 t4 = t1.operator+(t2) + t3 再转换为 t4 = t1.operator+(t2).operator+(t3) P387 错误:.*:成员指针运算符 修正:->:成员指针运算符 P428 错误: String boston("Boston"); 修正: StringBad boston("Boston"); P431 错误:然后程序使用重载运算符>>列出了这些对象 修正:然后程序使用重载运算符<<列出了这些对象 P439 错误:最简单的办法是使用标准的 trcmp()函数 修正:最简单的办法是使用标准的 strcmp()函数 P440 错误: means.operator[][0] = 'r'; 修正: means.operator[](0) = 'r'; P439 错误:因为内置的>运算符返回的是一个布尔值 修正:因为内置的<运算符返回的是一个布尔值 P478 错误: Cow(const Cow c& ); 修正: Cow(const Cow & c); P478 错误:提供一个 Stringlow()成员函数 修正:提供一个 stringlow()成员函数 P478 错误:提供 String()成员函数 修正:提供 stringup()成员函数 P505 错误: 这意味着,即使基类不需要显式析构函数提供服务,也不应该依赖于默认构造函数 修正: 这意味着,即使基类不需要显式析构函数提供服务,也不应该依赖于默认构造析构 P508 错误:半长轴 修正:长半轴 P510 错误: void Move(int nx, ny) = 0 修正: virtual void Move(int nx, ny) = 0 P525 错误: Star::Star double() {...} Star::Star const char * () {...} 修正: Star::operator double() {...} Star::operator const char * () {...} P529 错误:派生类的有元函数 修正:派生类的友元函数 P532 错误: Cd(char * s1, char * s2, int n, double x); 修正: Cd(const char * s1, const char * s2, int n, double x); P532 错误:派生出一个 Classic 类,并添加一组 char 成员 修正:派生出一个 Classic 类,并添加一个 char 数组成员 P532 错误: copy.Report() 修正: copy.Report(); P535 错误:所有元素度被初始化为指定值的数组 修正:所有元素都被初始化为指定值的数组 P544 错误:例如,在类声明中提出可以使用 average()函数。和包含一样,要实现这样的目的,可以在公有 Student::average()函数中使用私有 Student::Average()函数。 修正:例如,对于类 Student 需要提供的 Average()函数,与包含版本一样,私有继承版本同样可以借用 valarray 的 size()和 sum()方法来实现。 P549 错误:和私有私有继承一样 修正:和私有继承一样 P551 错误:这里使用两个独立的派生使基类( Worker )被继承 修正:从基类( Worker )继承出两个独立的派生类 P555 错误: Enter waiter's name: Waldo Dropmaster ... Enter singer's name: Sylvie Sirenne 修正: Enter worker's name: Waldo Dropmaster ... Enter worker's name: Sylvie Sirenne P573 错误:只有一个 pop 变量 修正:只有一个 po 变量 P583 错误: template <> class SortedArray<const char char*> 修正: template <> class SortedArray<const char*> P656 错误: string(const string & str, string size_type pos, size_type n = npos) 修正: string(const string & str, size_type pos, size_type n = npos) P729 错误:将 li 重置为排序的 vi0 的内容 袖子:将 li 重置为未排序的 vi0 的内容 P773 错误: ofstream fout(); 修正: ofstream fout; P794 错误: Store 的构造函数应接受一个指定 ifstream 对象的参数 修正: Store 的构造函数应接受一个指定 ofstream 对象的参数 P835 错误:*pt = ai[i]; 修正:*pt = ar[i]; |