作者LPH66 (かつて交わした约束)
看板C_and_CPP
标题Re: [问题] std::shared_ptr std::vector
时间Fri Sep 29 01:14:32 2017
先回答你的问题
首先一个观念, shared_ptr 跟 unique_ptr 的设计
就是你可以把这个变数「当成指向物件的指标变数来使用」
例如对 Foo* pFoo = new Foo(); 可以 pFoo->bar();
那 shared_ptr<Foo> spFoo (new Foo()); 也就可以 spFoo->bar();
不过上面那句「当成」有个但书是「你不能对它进行指标算术 (包含阵列存取)」
因为概念上这些东西是用来管理一个物件的, 对这物件之外的地方存取没有意义
所以虽然可以 *spFoo 取得所管理的物件, 但不能写 spFoo[0] 做阵列存取
====
那麽这里就要回到你一开始的指标版本了
你在宣告了 std::vector<std::vector<int>> *p = ...; 之後
下面直接使用了 p[0] 去取得这个物件
(像是 p[0].size() 去取得外层长度, 或 p[0][0] 取得第一列等等)
虽然你取到了, 但这只是因为它是指标变数所以 *p 等同 p[0] 而已
这里正确的取法是要使用 *p 去取得物件 (它又不指向一个阵列为什麽要 [0] ?)
(也就是像上面那个要写成 (*p).size() 和 (*p)[0] 才对)
这即是造成了你换成 shared_ptr 之後编译不过的原因
不然理论上指标版本的程式码跟 shared_ptr / unique_ptr 版本的程式码
应该是无痛转换的才对
====
然而 (这里算是一部份的题外话)
使用动态配置产生一个 vector 物件是有点叠床架屋的
因为 vector 自己本身就是使用动态配置来配置它的阵列内容的
(也因此才能够随意增加长度)
vector 的本体其实相对很小, 没记错应该等同数个 int 大小而已
传来传去的成本也并不高
这也就是为什麽推文一开始在问你「为什麽不直接宣告 vector 物件」的原因
====
再延伸出去一点
相对於 shared_ptr / unique_ptr 是对「(动态配置物件的)指标」的包装
vector 则是对「(动态配置的)阵列」的包装
也就是设计上 vector 才是使用阵列的存取方式 (也就是 [] 的方式)
这同时也呼应到版上常常看到很多人在讲的「指标不等於阵列」这句话
对一般的指标来说, 虽然编译到底层的机械码是一样的, 但上层的语意不同
而 shared_ptr / unique_ptr 跟 vector 即是分别抓取这两种语意做为存取介面
因此在使用时不能混用这两种存取介面
--
有人喜欢边
玩游戏边
上逼;
也有人喜欢边
听歌边
打字。
但是,我有个请求,
选字的时候请
专心好吗?
-- 改编自「古 火田 任三郎」之开场白
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 123.195.9.46
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1506618874.A.FFC.html
1F:→ PkmX: std::{shared,unique}_ptr之後可以用在T[]上 09/29 03:58
4F:→ LPH66: 比较了 std::vector, std::array 跟 std::unique_ptr<T[]> 09/29 09:41
5F:→ LPH66: 它们的各个方面, 三种各擅胜场在有相对的需求时确实好用 09/29 09:42
6F:→ LPH66: 所以我这篇文章比较没有着重在哪个状况要用哪个 09/29 09:43
7F:→ LPH66: 而是在解释它们的设计概念跟语意 09/29 09:44
8F:→ LPH66: 再说我也没有完全否定 shared_ptr<vector<T>> 就是 09/29 09:45