在堆?还是栈? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
814084764
V2EX    程序员

在堆?还是栈?

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

    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     Solana     2673 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 13:39 PVG 21:39 LAX 06:39 JFK 09:39
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86