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

在堆?还是栈?

  •  
  •   814084764 · 2018-09-25 17:41:45 +08:00 · 4355 次点击
    这是一个创建于 2247 天前的主题,其中的信息可能已经有所发展或是发生改变。

    C++

    class Target{ private: int a; }

    class Object { private : Target target; }

    Object* obj = new Object;

    请问:target 是在堆上?还是栈上??

    30 条回复    2018-09-26 16:22:44 +08:00
    poorcai
        1
    poorcai  
       2018-09-25 17:46:09 +08:00 via iPhone
    堆上
    poorcai
        2
    poorcai  
       2018-09-25 17:46:28 +08:00 via iPhone
    @poorcai #1 说错,在栈上
    innoink
        3
    innoink  
       2018-09-25 17:47:44 +08:00
    private : Target target;
    这只是一个结构描述,并不是实际会执行的语句。
    所以,肯定是都在堆上啊
    tinykey
        4
    tinykey  
       2018-09-25 17:48:30 +08:00
    堆上啊大兄 dei
    000wangxinyu000
        5
    000wangxinyu000  
       2018-09-25 17:50:03 +08:00
    @poorcai 为啥在栈上啊
    current
        6
    current  
       2018-09-25 17:50:21 +08:00
    @poorcai 为啥是栈? CPP 同一个 instance 还能拆成几块,一部分在堆上一部分在栈上不成
    innoink
        7
    innoink  
       2018-09-25 17:51:09 +08:00
    同样是 int a; 在一个函数里这句话会被执行,作用是开一个局部变量
    在一个结构描述里,这句话不会被执行,只是起到描述作用,有这么一个类型的成员,具体成员放在哪不管
    814084764
        8
    814084764  
    OP
       2018-09-25 17:51:56 +08:00
    @innoink 不是在创建的时候自动调用成员变量的构造方法么?

    @tinykey 这个 target 不是程序员需要手动释放的,不是在栈上么?
    814084764
        9
    814084764  
    OP
       2018-09-25 17:53:23 +08:00
    @innoink 也就是说,在创建 Object 的时候,不会自动调用成员变量 target 的构造方法了?

    @current 不可以吗?不知道。。哈哈
    innoink
        10
    innoink  
       2018-09-25 17:53:26 +08:00
    @innoink 构造方法里面也不是 int a;啊
    都是类似这种:
    this->a = parameter_a;这样的
    iceheart
        11
    iceheart  
       2018-09-25 17:54:18 +08:00 via Android
    只能说是 new 出来的,想把它摆在栈上也不难
    innoink
        12
    innoink  
       2018-09-25 17:54:44 +08:00
    @814084764 构造方法中,没有办法知道自己是在栈上还是在堆上。构造方法只是用来初始化成员的,并不能用来产生成员。
    814084764
        13
    814084764  
    OP
       2018-09-25 17:57:56 +08:00
    @innoink 可能我的例子写的不全。
    比如 Target 有一个函数:int getA(){return a };

    Object 中调用 target.getA()。这个时候已经产生成员了吧?
    这个时候 target 是在堆还是栈呢?
    bytelee
        14
    bytelee  
       2018-09-25 18:01:00 +08:00
    target 在哪 取决于你是怎么生成的他吧
    innoink
        15
    innoink  
       2018-09-25 18:01:42 +08:00
    @814084764 Object 中调用 target.getA()
    你要在哪里调用这个? Obejct 的构造函数吗?还是一样的。在 obj 创建之时,在 Object()调用之时,target 就已经有内存了,只不过没有初始化。Object()的作用只是初始化 target,并不能决定 target 在哪里分配。
    MeteorCat
        16
    MeteorCat  
       2018-09-25 18:13:50 +08:00 via Android
    按你生成的方式决定
    innoink
        17
    innoink  
       2018-09-25 18:20:57 +08:00
    @814084764 你的意思可能是:
    class Object
    {
    public:
    int foo()
    {
    return target.getA();
    }
    private:
    Target target;
    }

    首先,这里还是不知道 target 是在堆上还是栈上,但是没关系,就算 target 没分配内存,getA()的函数代码都在那里,都能调用。你要是问"target 都没有怎么返回 a"?成员函数隐含传入 this 指针,只要运行时 this 指针能确定就行了;在 foo 里面,也会有 Object 的 this 指针,通过偏移量能计算出 target 的 this 指针传给 getA()。
    linghutf
        18
    linghutf  
       2018-09-25 19:43:21 +08:00
    堆上,Target target 只是声明了一个对象,还没有实例化,在 new Object 后调用其默认构造函数,于是 target 初始化到堆上。
    broker
        19
    broker  
       2018-09-25 20:00:55 +08:00
    可以把 target 改成一个大数组,直到报错,看看报什么错。。。
    tangweihua163
        20
    tangweihua163  
       2018-09-25 21:06:27 +08:00
    一个实例部分在栈上部分在堆上还真是常有的事。
    bumz
        21
    bumz  
       2018-09-25 21:12:47 +08:00
    Object 在堆的时候在堆,Object 在栈的时候在栈

    习惯了 java 是不是很难受 hhh
    zwh2698
        22
    zwh2698  
       2018-09-25 21:25:40 +08:00 via Android
    Target 改什么都在堆上,内存的分配主要是开对象分配的方式,如果 new 和 placement new 一般在堆,但是后者可以放在栈上,那也是提前你保留了。栈都是编译时候就决定了,大小在这个时候一定可以推导出来,堆是在运行时候分配,大小要看上下文
    senxxx
        23
    senxxx  
       2018-09-25 22:44:15 +08:00 via Android
    @poorcai 大兄弟。在栈上的话。。如果 obj 指针被作为返回值返回给上一层。。那此时的 target 是个什么情况?
    yujincheng08
        24
    yujincheng08  
       2018-09-25 22:52:14 +08:00 via Android
    linshuang
        25
    linshuang  
       2018-09-26 09:22:30 +08:00
    肯对是堆,要是栈,你觉得它能用么。。。
    seancheer
        26
    seancheer  
       2018-09-26 09:50:01 +08:00
    堆啊。。

    target 占用的内存是属于 new 出来的 obj 的,obj 是你 new 出来的,那么就在堆上。

    如果直接 Object obj,那么就是在栈上面。

    class Object 的时候,这个属于声明,不会占用内存的。
    justou
        27
    justou  
       2018-09-26 10:23:53 +08:00
    堆上. 不能在栈上的原因上面提到了. C++也可以 new 在栈上, 叫 placement new, 在某些场景下非常有用

    https://www.geeksforgeeks.org/placement-new-operator-cpp/
    wizardoz
        28
    wizardoz  
       2018-09-26 12:47:59 +08:00
    凡是 new 的都在堆上
    cuzfinal
        29
    cuzfinal  
       2018-09-26 14:22:16 +08:00
    当然是在堆上了,难道 object 里 int a = 1 会在栈上吗?
    dychenyi
        30
    dychenyi  
       2018-09-26 16:22:44 +08:00
    堆上啊。
    反证法:Target target 如果在栈生成,每个类都是由子类和数据类型构成的,那么没有一个类能在堆上了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1426 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 17:26 · PVG 01:26 · LAX 09:26 · JFK 12:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.