我正在学习C ++ 11的功能,作为其中的一部分,我首先潜入unique_ptr
和shared_ptr
的世界。
当我开始时,我写了一些专门使用unique_ptr
的代码,因此当我传递我的变量时,我需要用std::move
完成它(或者我理解了)
经过一番努力,我意识到我真的需要shared_ptr
而不是我正在做的事情。稍后快速查找/替换,我的指针被切换为共享,但我懒得离开move()
来电。
令我惊讶的是,这不仅仅是编译,而且在我的程序中表现得非常好,我得到了我期待的每一项功能......特别是,我能够"移动"从ObjectA到ObjectB的shared_ptr
,两个对象都可以访问它并可以对其进行操作。奇妙。
这为我提出了一个问题,但是...... move()
现在shared_ptr
实际上正在做任何事情吗shared_ptr<Label> lblLevel(new Label());
//levelTest is shared_ptr<Label> declared in the interface of my class, undefined to this point
levelTest = lblLevel;
//Configure my label with some redacted code
//Pass the label off to a container which stores the shared_ptr in an std::list
//That std::list is iterated through in the render phase, rendering text to screen
this->guiView.AddSubview(move(lblLevel));
?如果是这样,它会产生什么影响呢?
代码示例
levelTest
此时,我可以对levelTest进行重要更改,例如更改文本,这些更改会反映在屏幕上。
这对我来说似乎move()
和列表中的shared_ptr都是相同的指针,而{{1}}确实没有做太多。这是我的业余解释。寻找洞察力。在Windows上使用MinGW。
答案 0 :(得分:4)
ecatmur的回答解释了为什么你会在一般意义上看到事物的行为。
特别针对您的情况,levelTest
是lblTest
的副本,它创建了对共享资源的额外拥有引用。您从lblTest
移出,因此levelTest
完全不受影响,且资源的所有权保持不变。
如果您查看lblTest
我确定您已将其设置为空值。因为您在移动它之前制作了shared_ptr
的副本,所以指针的现有实例(levelTest
和guiView
中的值)都应引用相同的基础指针(他们的get
方法返回相同的值)并且应该至少有两个引用(他们的use_count
方法应该返回2
,如果你做了额外的副本,则更多。)
shared_ptr
的重点在于,在所有shared_ptr
个实例都被销毁的情况下仍然允许自动清理资源时,启用像您一样的内容。
答案 1 :(得分:3)
当您从可转换类型的共享指针移动构造或移动分配时,源指针变为空,符合20.7.2.2.1:
22 - 后置条件:
*this
应包含旧值r
。r
应为空。r.get() == 0
。
因此,如果您在移动构造或移动分配后观察到源指针仍然有效,那么您的编译器不正确或者您使用的std::move
不正确。
例如:
std::shared_ptr<int> p = std::make_shared<int>(5);
std::shared_ptr<int> q = std::move(p);
assert(p.get() == nullptr);
答案 2 :(得分:2)
如果你复制一个shared_ptr,指针目标的引用计数会递增(以线程安全的方式)。
相反,当您将一个shared_ptr从A移动到B时,B包含移动前A的状态副本,而A为空。没有线程安全的引用计数递增/递减,但A和B的内部位之间有一些非常简单和便宜的指针交换。
您可以将移动视为&#34;从移动源移动到移动目的地的资源&#34; 的有效方式。