Sym*_*ion 3 c++ unique-ptr c++11
假设我有一个这样的类:
class Node {
public:
Node(Node* parent = 0) : mParent(parent) {}
virtual ~Node() {
for(auto p : mChildren) delete p;
}
// Takes ownership
void addChild(Node* n);
// Returns object with ownership
Node* firstChild() const;
// Does not take ownership
void setParent(Node* n) { mParent = n; }
// Returns parent, does not transfer ownership
Node* parent() const { return mParent; }
private:
list<Node*> mChildren;
Node* mParent;
};
Run Code Online (Sandbox Code Playgroud)
我现在想使用智能指针和/或右值引用来指示所有权在哪里和不被转移.
我的第一个猜测是改为mChildren包含unique_ptrs,调整功能签名如下.
// Takes ownership
void addChild(unique_ptr<Node> n);
// Returns object with ownership
unique_ptr<Node>& firstChild() const;
// Does not take ownership
void setParent(Node* n) { mParent = n; }
// Returns parent, does not transfer ownership
Node* parent() const { return mParent; }
Run Code Online (Sandbox Code Playgroud)
现在,当我需要传递的结果,这将是一种有问题的Node::firstChild()一些功能观察它,但没有取得所有权,因为我需要显式调用.get()的unique_ptr,这是我的理解,不建议使用.
什么是正确和推荐的方式来指示所有权使用unique_ptr而不必诉诸于使用.get()和传递裸指针?
起初,我会使用std::vector而不是std::list包含孩子.除非你有强烈的动机不使用它,std::vector否则应该是默认容器.如果您担心性能,请不要这样做,因为完成的连续分配std::vector可能会导致更高的缓存命中率,从而极大地加快了访问速度std::list,这意味着分散的分配/访问模式.
其次,你有一个std::vector<std::unique_ptr<Node>>抱孩子是正确的,因为假设一个节点拥有其子节点的所有权是合理的.addChild()另一方面,除了接受的指针之外的所有其他指针应该是非拥有的原始指针.
这适用于mParent指针和由Node成员函数返回的指针.实际上,firstChild()成员函数甚至可以返回引用,如果节点没有子节点则抛出异常.通过这种方式,您不会对拥有返回对象的人产生任何混淆.
返回a unique_ptr或对a的引用unique_ptr不是正确的习惯用法:唯一的指针代表所有权,并且你不想给予客户的所有权Node.
这就是你的课程的样子:
#include <vector>
#include <memory>
#include <stdexcept>
class Node {
public:
Node() : mParent(nullptr) { }
void addChild(std::unique_ptr<Node>&& ptr) {
mChildren.push_back(std::move(ptr));
ptr->setParent(this);
}
Node& firstChild() const {
if (mChildren.size() == 0) { throw std::logic_error("No children"); }
else return *(mChildren[0].get());
}
Node& parent() const {
if (mParent == nullptr) { throw std::logic_error("No parent"); }
else return *mParent;
}
private:
void setParent(Node* n) {
mParent = n;
}
std::vector<std::unique_ptr<Node>> mChildren;
Node* mParent;
};
Run Code Online (Sandbox Code Playgroud)
如果你想避免抛出异常,你当然可以决定返回非拥有的,可能为null的原始指针而不是引用.或者您可以添加一对hasParent()和getNumOfChildren()方法来检索有关Node状态的信息.这将允许客户端执行检查,如果他们不想处理异常.
| 归档时间: |
|
| 查看次数: |
1516 次 |
| 最近记录: |