Re: [问题] std::shared_ptr std::vector

楼主: LPH66 (-6.2598534e+18f)   2017-09-29 01:14:32
先回答你的问题
首先一个观念, 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 即是分别抓取这两种语意做为存取接口
因此在使用时不能混用这两种存取接口
作者: PkmX (阿猫)   2017-09-29 03:58:00
std::{shared,unique}_ptr之后可以用在T[]上http://coliru.stacked-crooked.com/a/f17781559d36eb92
楼主: LPH66 (-6.2598534e+18f)   2017-09-29 09:40:00
关于这个, https://stackoverflow.com/a/16804634 这个回答比较了 std::vector, std::array 跟 std::unique_ptr<T[]>它们的各个方面, 三种各擅胜场在有相对的需求时确实好用所以我这篇文章比较没有着重在哪个状况要用哪个而是在解释它们的设计概念跟语意再说我也没有完全否定 shared_ptr<vector<T>> 就是

Links booklink

Contact Us: admin [ a t ] ucptt.com