C_and_CPP 板


LINE

▉▂开发平台(Platform): (Ex: Win10, Linux, ...) MacOSX 编译器(Ex: GCC, clang, VC++...)+目标环境(跟开发平台不同的话需列出) g++5.4 问题(Question): 大家好,最近在修资料结构这门课,过去虽然有修过计算机程式 ,但是两学分的课所以感觉学得不是很扎实,对於class的部分只有粗略带过.. 所以来这边请教大家: 对於一个data member中含有pointer的class,初始时会用new配置记忆体, 而自行建立的destructor会用delete释放配置给该指标的记忆体,请问这样的状况下 该怎麽在member function中回传一个local的class变数呢? 因为函数功能的需要,必须在函数中宣告一个class变数a来承接运算的结果,并return 该变数给calling function,由calling function中的class变数b承接,但是这样的情 况下,由於member function terminates, destructor将a里面的pointer给delete掉, 造成calling function中b里面的指标指向一个直随时有可能被修改的地方... 有自己试着去overload operator=及建立copy constructor来看看是否可以让calling function 中b里面的pointer指向一个新的地方,在复制a的值过去,但好像a会先被 destructed(?!).. 上网查了很多destructor, return object的关键字,都找不到想要的答案.. 在这里麻烦大家解答了.. 在下面附上class 的程式码,大致上是我在建立一个stack的class 有一个destructor: ~Stack(){delete [] stack 初始的constructor有用new给该指标动态配置记忆体 问题卡在是我要写一个member function splitStack(),作用是要将某个stack从中间 某个点分开拆成两个stack,所以这个function 必须return stack型态的variable, 但是splitStack()中宣告的first再回传值给main後,就被解构了.. 程式码(Code):(请善用置底文网页, 记得排版) http://codepad.org/IjGU1cDW --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 114.47.182.50
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1507466726.A.1A7.html
1F:推 jerryh001: 是要定义copy constructor没错 看看有没有哪里写错 10/08 21:07
2F:→ jerryh001: 发现个奇怪的地方 destructor不应该手动呼叫 10/08 21:08
3F:→ s5031588: 请问j大 copy constructor该怎麽写呢?因为我造我的逻 10/08 22:07
4F:→ s5031588: 辑写还是没办法欸..附上我copy constructor的程式码: 10/08 22:08
5F:→ s5031588: http://codepad.org/hP4cyP6b 10/08 22:17
6F:→ s5031588: 顺便附上main的程式码http://codepad.org/TcOdcyCc 10/08 22:20
7F:→ s5031588: 我用一步步执行发现,虽然copy function不会让两个 10/08 22:21
8F:→ s5031588: POINTER 直接相等,但是splitStack一结束,居然会 10/08 22:22
9F:→ s5031588: 两个指标都destruct...= =,有人可以解释原理吗QQ 10/08 22:22
10F:→ jerryh001: operator=也要留吧 10/08 22:40
11F:→ jerryh001: copy ctor 的参数也许也要<T>吗? 有点忘了 10/08 22:42
12F:→ stucode: 怎麽写完 copy ctor 後 operator = 就不见了XD? 10/08 23:20
13F:→ stucode: 1. copy constructor 里面不用 delete,因为是初始化, 10/08 23:20
14F:→ stucode: 还没有前值,直接 new 然後 copy 就好。 10/08 23:20
15F:→ stucode: 2. copy assignment 需要检查并释放(或重新利用)现有 10/08 23:20
16F:→ stucode: 资源,同时要避免 self-assignment 造成错误的 10/08 23:21
17F:→ stucode: delete。 10/08 23:21
18F:→ stucode: 3. copy assignment 请传回 reference,不要传值。 10/08 23:21
19F:→ stucode: 4. splitStack() return first 就好,不用再包一层。 10/08 23:21
20F:→ stucode: 其实你的指标几乎都是在 3. 或 4. 多余的临时物件中被 10/08 23:21
21F:→ stucode: delete 掉的。不过如果有做好 deep copy,顶多就是多跑 10/08 23:22
22F:→ stucode: 几次 copy 效能较差而已,也不至於会使用到被 delete 10/08 23:22
23F:→ stucode: 掉的指标,造成严重错误。 10/08 23:22
喔喔喔了解了,真的是犯傻才会把operator=又删掉XDD,现在程式可以work了, 非常感谢j大跟s大的解说! 不过想另外请教s大,关於第三点,为什麽会说传回reference呢?是因爲传回值 有什麽缺点吗?谢谢。 ※ 编辑: s5031588 (114.47.182.50), 10/09/2017 00:44:19
24F:推 lc85301: 传回reference 是要允许使用 move 来减少一次 copy 吧 10/09 01:04
25F:→ stucode: 传回值的话,比较容易产生不必要的临时物件。除此之外, 10/09 05:57
26F:→ stucode: 还可能导致非使用者预期的行为。其实 C++ 并没有硬性规 10/09 05:57
27F:→ stucode: 定 copy assignment 要传回 reference。这比较像是一种 10/09 05:57
28F:→ stucode: 惯例,让自定义类别的行为尽可能相似於 C++ 原生型别 10/09 05:58
29F:→ stucode: (如 int)的行为。减少类别使用时产生意料之外的效果。 10/09 05:58
30F:→ stucode: 另外一个理由是,CopyAssignment requirements 要求回传 10/09 05:58
31F:→ stucode: 型态必须是 T&,没有满足这个条件可能无法正常使用某些 10/09 05:58
32F:→ stucode: 标准容器的方法。事实上,如果没有为类别宣告这个函数, 10/09 05:58
33F:→ stucode: 编译器自动帮你生成的版本也是传回 reference。当然,如 10/09 05:58
34F:→ stucode: 果你有更好的理由传回新物件或者是其他型别,那就不用客 10/09 05:58
35F:→ stucode: 气的传吧!只要确保使用者了解并正确使用你的类别即可。 10/09 05:59
谢谢s大与l大的回覆,原来回传值会产生一个临时物件,一直以为回传的值会直接 回到main,由main里面的物件去接收...看来我原本误会很深 再次感谢三位的回覆。 ※ 编辑: s5031588 (49.215.209.133), 10/09/2017 09:16:04
36F:推 james732: 顺便学一下什麽是rvalue reference与move吧XD 10/09 10:02
回james:好的我会研究看看,谢谢建议。 照着大家说得下去改了程式码:http://codepad.org/RYcz2e7B main:http://codepad.org/cM17bFfK 为什麽我原本用b=a.splitStack(1)的时候,当等式结束的时候splitStack()里面的first 会被destructor给删除,然而改成上面main里面的方式用Stack b(a.splitStack(1))时, 却没有呼叫destructor来解构first的迹象...? 另外,为什麽用copy assignment的时候,似乎是等到等号结束时,程式才会呼叫 destructor来解构first,而不是splitStack一结束就呼叫呢? 我好乱啊..QQ ※ 编辑: s5031588 (49.215.209.133), 10/09/2017 10:52:07
37F:→ Caesar08: 如果你想要预先allocate一些memory来用,你需要知道 10/09 13:50
38F:→ Caesar08: placement new才行。今天destructor没问题是因为T是int 10/09 13:50
39F:→ Caesar08: 建议先看gcc或msvc的vector怎麽实作vector,再实作stack 10/09 13:51
40F:→ stucode: 实测了一下,解构都正常喔。如果你有开最佳化(或者是 10/09 20:09
41F:→ stucode: IDE 的 Release mode),那 first 可能被 RVO 掉,实际 10/09 20:09
42F:→ stucode: 解构会在 b 生命周期结束时(离开 main() 时)发生。 10/09 20:09
43F:→ stucode: 另外,复制建构函数里的 new 括号错了。 10/09 20:09
谢谢c大的回答,我会再参考看看。 回s大:我不知道我有没有开最佳化欸,我不管在xcode里面跑(似乎是debug mode 我也不知道怎麽看,整个IDE我只会有按过run跟新增专案而已..惨)还是用终端机跑 g++-5 main.cpp的指令出来的结果就是destructor只被呼叫了两次(最後离开main的时 候),後来一步步看,似乎跑的时候系统一开始就直接把first.stack与b.stack指向 同一个地方了,所以最後destructor只有呼叫两次,一次是delete a.stack 另一次是delete b.stack(first.stack),似乎这就是s大你说的first被RVO.. 再次感谢s大,还让你帮我跑一次~ ※ 编辑: s5031588 (36.236.99.33), 10/10/2017 12:16:25







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Tech_Job站内搜寻

TOP