V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
superhxnju
V2EX  ›  C

c++菜鸡求助

  •  
  •   superhxnju · 2015-11-03 21:42:40 +08:00 · 1450 次点击
    这是一个创建于 3088 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码

    #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.

    Alt text

    疑问:
    - 函数 clone 中是否在堆中新分配了内存给*p?(个人认为不是,根据地址来看,地址属于栈)
    - 为什么书中写到是隐式调用了 new ,但是当 delete 的时候出现pointer being freed was not allocated的错误?


    环境
    - mac
    - g++
    - c++11

    10 条回复    2015-11-04 09:38:38 +08:00
    colatin
        1
    colatin  
       2015-11-03 21:53:46 +08:00
    建议把 c 的指针学好先。
    A *p; *p = a;
    这里的 p 就是个野指针。*p=a 相当于在一个不知道什么地方的地方写了一个值。
    superhxnju
        2
    superhxnju  
    OP
       2015-11-03 21:59:46 +08:00
    @colatin 大概知道是个野指针,但就是书看到这里的时候很困惑。书里面的这段是我理解有误。。。还是就是有问题?
    Ethaniz
        3
    Ethaniz  
       2015-11-03 22:00:41 +08:00
    没听说过 clone 会隐式调用 new 呢,你这里的情况是:在 clone 中声明了一个栈变量,类型是个指针,指向地址随机,然后把这个指针指向的地址赋上了 a 的值,然后又返回了这个指针指向的值的引用。函数调用结束,该指针消失。自始至终没有向堆申请任何空间,所以导致 delete 失败。
    theoractice
        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/
    看这些足够了。
    superhxnju
        5
    superhxnju  
    OP
       2015-11-03 22:22:23 +08:00 via iPhone
    @theoractice 看的是 c++ primer plus ,重拾一下 c++
    superhxnju
        6
    superhxnju  
    OP
       2015-11-03 22:24:36 +08:00 via iPhone
    @theoractice 看看基础就行
    znoodl
        7
    znoodl  
       2015-11-03 22:43:09 +08:00 via iPhone
    经典的不是 c++ primer 吗? 不带 plus ,不是一个作者,书里有 delete 的例子吗
    superhxnju
        8
    superhxnju  
    OP
       2015-11-03 22:54:33 +08:00 via iPhone
    @znoodl 被名字给欺骗了
    SYP
        9
    SYP  
       2015-11-03 23:25:48 +08:00
    这样的代码这本书还说的一本正经,还是放弃掉吧。
    yangyanggnu
        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];
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4193 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 04:12 · PVG 12:12 · LAX 21:12 · JFK 00:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.