×

Loading...

Topic

This topic has been archived. It cannot be replied.
  • 工作学习 / IT技术讨论 / 国内一家公司招聘C++ Programmer的面试题:
    以下程序预期得结果15, 15, 16,但实际得结果15, 16, 16,为何?

    // start of code
    #include <stdio.h>

    class X
    {
    public:
    int *px;
    X ( int init )
    {
    px = new int; *px = init;
    }
    ~X () {
    delete px;
    }
    };

    void print ( X x )
    {
    printf ("%d\n", *x.px);
    }

    int main ()
    {
    X x(15); print(x);
    X y(16); print(x); print(y);

    return 0;
    }

    // end of code
    • 把对象直接当参数传递,函数里用完就释放了
    • 说得再清楚一些
      X x(15);
      print(x);
      当到这里完成打印时,delete px 被调用,因为是传对象,函数结束
      时要执行一次释放动作。假设指针px经过new之后占有单元0x30009876,那么delete px 后,0x30009876又是第一个可用单元。

      X y(16);
      px 又指向(占有)0x009876单元, *px=16使这个单元存放值16。

      print(x);
      *x.px 实际上就是引用0x009876单元里面的值。你说这个值现在是多少呢?

      print(y);
      实际上在VC++中不工作,得一UNDEFINE的值。
      • Sorry
        X x(15); //px 指向单元0x30009876, *px=15意味着这个单元存放值15
        print(x); // 当到这里完成打印时,delete px 被调用,因为是传对象,函
        //数结束时要执行一次释放动作。假设指针px经过new之后占有
        //单元0x30009876,那么delete px 后,0x30009876又是第一个可
        //用单元。
        X y(16); //px 又指向(占有)0x30009876单元, *px=16使这个单元存放值
        //16。

        print(x); //*x.px 实际上就是引用0x30009876单元里面的值。你说这个值
        //现在是多少呢?

        print(y); //实际上在VC++中不工作,得一UNDEFINE的值。
        • Since this code has memory leak, I don't think 15,16,16 is guranteed, it depends on the compiler
          • you are correct
      • 完全正确!这在UNIX下编译是可以的。修改的方法是将print中参数形式改为const &或const *.或者定义拷贝构造函数,因为题中调用缺省的拷贝构造函数是将成员一一拷贝,而不拷贝指针指向的数值。
    • it is caused by memory destruction
      When print(X x) is invoked, a copy of object x is generated(say x1), x1's member px points at same memory address of member px of the orginal object x. Thus when print returns, x1 is released and destructor ~x is excuted to delete px.
      When statement X y(16); is excuted, its constructor allocates a new memory for its member px at the same address as in object x and stores 16 in it. Since the member px of object x keeps same address as in y, print(x) will print 16 and destroy memory px. Afterwards, when print(y) is excuted, since memory px is deleted, a random value is printed and then an error about deleting unexist memory is raised.
      It seems not easy to be understood. But if you can understand it completely, I think you can improve your c/c++ skills a lot.
      • 请问这句话怎么理解?allocates a new memory for its member px at the same address as in object x and stores 16 in it.
        since allocate a new memory then how come "at the same address" ?

        1- why at the same address?
        2- how to fix the problem??

        thanks!
        • if you read my article.......
          when you call int *a =new int(10);,a points to a first available memory unit 0x12345678 which stores 10.

          when you call delete a, memry unit 0x12345678 becomes first available memory unit again.

          when you call int *b= new (11);, b points to 0x12345678 again.

          is that clear?
          • so it seems allocating the same address is decided by the run time? why i did not see it in books before when i read the part of dynmaic memory management? i' ll check in again. thanks!
        • It's heap management, a block of the size int was just deleted (first print(x)), then u try to alloc the same size (Y(16)), sure the heap manager will give u the same addr.
          To avoid, if u must use pointer in class, u can:
          1. everytime use this class type as parameter, pass it by pointer or reference (can make a private copy constructor to ensure it)
          2. or implement ur own copy constructor, when copy, alloc another heap for the created new instance
          3. or use some kind of smart pointer (keep monitoring the reference counter of the pointor, if it's 0 then do the real deletion)

          Also, a good programming style: assign null to pointer after operator delete, and check if the pointor is null b4 u delete it
      • I agree with you. This is a very bad and wrong program. It will cause memory destruction when print(y) is called.
      • one way to fix it
        void print ( X& x )
        {
        printf ("%d\n", *x.px);
        }
    • So always keep this in mind: when there is a pointer member in class, define your own copy constructor and overload assignment operator.
      • good comments. because you will never precisely know when your object will be copied silenty, secretly
      • good point