从 C++ 基础到掌握 — 第 9 集
用智能指针表达所有权
该博客上撰写的文章是出于教学目的而创建的。 另外,文章中的信息可能不正确,请谨慎。
使用指针不会引起问题。 当原始指针被用作所有权而不知道谁应该销毁该对象时,就会出现问题。
智能指针将所有权表示为一种类型。
unique_ptr
std::unique_ptr拥有独家所有权。
#include <memory>
auto warrior = std::make_unique<Warrior>("Rose");
std::cout << warrior->Attack() << '\n';
不直接调用newstd::make_unique创建一个对象 如果 unique_ptr 超出范围,则拥有的对象将自动销毁。
由于它是独占的,因此无法复制,但可以移动。
std::vector<std::unique_ptr<Character>> party;
auto warrior = std::make_unique<Warrior>("Rose");
party.push_back(std::move(warrior));
std::move之后,战士变为空,所有权转移到向量。 std::move 本身将其视为可移动值,而不是移动对象的函数。
shared_ptr
单个怪物可能需要同时属于活动列表和战斗系统。 此时std::shared_ptr可以使用。
auto monster = std::make_shared<Monster>(1, "Slime", 30);
std::vector<std::shared_ptr<Monster>> activeMonsters;
std::queue<std::shared_ptr<Monster>> spawnQueue;
spawnQueue.push(monster);
activeMonsters.push_back(monster);
当shared_ptr被复制时,对象并没有被复制,但是它的引用计数会增加。 当它的最后一个所有者消失时,实际的对象就会被销毁。
仅仅为了方便而将所有指针都放入shared_ptr并不是一个好主意。 谁拥有它变得不清楚,可能会发生循环引用,并且存在引用计数管理成本。
weak_ptr
如果您不拥有像当前目标这样的对象并且只想观察它,std::weak_ptr使用 。
std::weak_ptr<Monster> currentTarget;
currentTarget = monster;
if (auto target = currentTarget.lock())
{
std::cout << target->GetHealth() << '\n';
}
weakptr 不会延长对象的生命周期。 如果对象还活着lock()返回此sharedptr,或者如果它已经被销毁,则返回一个空的shared_ptr。
总结一下,如果只有一个所有者 uniqueptr, 如果多个系统确实需要拥有sharedptr, 如果你只是查看而不拥有它,那么它就是weak_ptr。
当代码中显示所有权时,就不用担心何时删除。