我知道,std::shared_ptr
使用引用计数,因此它具有复制和移动语义,另一方面std::unique_ptr
(因此名称唯一)仅具有移动语义,因此尝试复制它是编译错误。
但是,对我而言,这个交易有多大不太清楚。在大多数情况下,我可以简单地使用std::shared_ptr
而不是std::unique_ptr
,或者我应该尽可能使用std::unique_ptr
,因为它不会更有效率,因为它不必采取照顾参考计数?
另外,我知道智能指针在处理时非常有用,例如异常安全性,但它们是否通常取代传统的T*
指针?
在可能的情况下使用智能指针而不是传统的T*
指针是一种很好的编程习惯吗?
答案 0 :(得分:5)
经验法则是:
在某些情况下,原始指针在没有所有权时也可以 - 例如作为函数的输入参数:
void draw (const shape* sh) {
sh->draw();
}
...
std::unique_ptr<shape> ptr(new triangle);
draw(ptr.get());
答案 1 :(得分:3)
shared_ptr
的问题是,afaik,引用计数是一个原子函数,这意味着它不仅计算引用,还具有锁定功能以确保函数是原子的。所以在这一点上,是的,当你只需要移动功能时,unique_ptr
更好用。
就个人而言,我不使用shared_ptr
很多,大多数普通指针都足够了。 Imho智能指针只会鼓励在内存管理方面变得懒散。我参与的项目中,智能指针在退出程序时只会导致竞争条件,因为没有人知道破坏的顺序,而这些指针引用了彼此。对于我自己,我只使用它们,如果我的一个lib指向外部,当它们被删除(或以何种顺序)时它是无关紧要的。
答案 2 :(得分:1)
您应该尽可能选择值rootComponent.anyPublicFunction(val);
和class Shipment < ActiveRecord::Base
belongs_to :user
has_many :vehicles, dependent: :destroy
validates :origin_id, :dest_id, :presence => true
attr_accessible :origin_id, :dest_id
belongs_to :origin, :class_name => 'Location', :foreign_key => 'origin_id'
belongs_to :destination, :class_name =>'Location', :foreign_key => 'dest_id'
end
到std::unique_ptr
,但不是出于性能原因。是的,当涉及std::unique_ptr
时会有一些开销,因为它们在某种形式的原子计数器中使用,但对于大多数应用程序来说这可以忽略不计。
使用std::shared_ptr
的主要原因是唯一性语义 - 当您(或其他人)读取代码时,对象的生命周期和所有权非常清楚。这使得更容易推理代码并找到逻辑/性能问题。
PS:std::shared_ptr
与原始指针相比没有开销,但它有一些很大的优势。
答案 3 :(得分:0)
如果传递给函数,则shared_ptr具有构造/销毁指针本身的额外成本,加上引用计数机制。
不要听任何人说要么智能指针总是要走的路,也不要听那些说原始指针总是更好的人。 有些情况下智能指针是有意义的,并且有原始指针是优选的情况。
如需更详细和全面的阅读,我建议您访问: http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
它涵盖了你提出的所有要点,大部分内容都很容易阅读。
答案 4 :(得分:0)
shared_ptr
表示资源周围的所有权规则很复杂。了解它们需要在一般情况下追踪所有shared_ptr
的生命周期。
unique_ptr
意味着围绕资源的所有权规则很容易。
两者都强制执行一组所有权规则,但unique_ptr
的规则是简单且本地的,shared_ptr
的规则是复杂且非本地的。如果你处于两种随意选择的情况,那么你就不会因为它们应得的引力而处理终身问题。
如果您有一个类似指针的资源,其生命周期应该简单地控制,或者甚至在某个具有复杂逻辑的中心位置(类型),请使用unique_ptr
。原始指针的成本很低,它添加(强制执行)文档,这是指向此资源的“拥有”指针。
如果必须拥有一个资源,其生命周期是一堆其他对象的生命周期的并集,所有这些对象的生命周期都不相关,则可以考虑shared_ptr
。如果你的情况如此复杂以至于可能形成一个循环,那么天真的shared_ptr
使用不再是一个实用的选择。
shared_ptr
和weak_ptr
也可以用作分布式生命周期通知系统,其中中心位置存储(主要是唯一的)shared_ptr
,客户端存储weak_ptr
。从shared_ptr
创建本地(非存储)weak_ptr
以检查目标资源是否仍然存在,然后操纵资源,然后丢弃本地shared_ptr
。这里的目标是(以非语言强制方式)使用弱共享的unique_ptr
,因此关于生命的推理仅比unique_ptr
情况稍微强一些。
shared_ptr
基本上从不“解决”终身问题而不证明它会解决你的终身问题。它可以使该证明的某些部分更容易。