移动语义和引用语义
我正在编写一个类似树的容器,其中每个“节点”都有一个包含分支/子树的列表,目前我的头看起来像:
class _tree {
public:
typedef _tree* tree_ptr;
typedef std::list<_tree> _subTreeTy;
explicit _tree(const _ValTy& v, const _NameTy& n); //create a new tree
_tree(const _ValTy& v, const _NameTy& n, tree_ptr _root);
//create a new tree and add it as branch to "_root".
~_tree();
void add_branch(const _tree& branch); //add by copy
void add_branch(_tree&& branch); //add by move
private:
_subTreeTy subtrees;
_ValTy value;
_NameTy name;
};
_tree::_tree(const _ValTy& v, const _NameTy& n, tree_ptr _root)
: root(_root),
value(v),
name(n)
{
_root->add_branch(*this); //not rvalue(???)
}
现在第二个构造函数将在 _root
内创建一棵树 - 但是如何这与调用一起工作(忽略私人违规):
_tree Base(0,"base");
_tree Branch(1, "branch", &Base);
Base.subtrees.begin()->value = 8;
std::cout << Branch.value;
我将如何做到这一点,以便 Branch
& *Base.subtrees.begin()
引用同一个节点?或者我应该走另一条路。使用add_branch()
创建分支/子树?
I'm writing a tree-like container, where each "node" has a list with branches/subtrees, currently my head looks like:
class _tree {
public:
typedef _tree* tree_ptr;
typedef std::list<_tree> _subTreeTy;
explicit _tree(const _ValTy& v, const _NameTy& n); //create a new tree
_tree(const _ValTy& v, const _NameTy& n, tree_ptr _root);
//create a new tree and add it as branch to "_root".
~_tree();
void add_branch(const _tree& branch); //add by copy
void add_branch(_tree&& branch); //add by move
private:
_subTreeTy subtrees;
_ValTy value;
_NameTy name;
};
_tree::_tree(const _ValTy& v, const _NameTy& n, tree_ptr _root)
: root(_root),
value(v),
name(n)
{
_root->add_branch(*this); //not rvalue(???)
}
Now the second constructor would create a tree inside _root
- however how does this work with calling (ignore private violation):
_tree Base(0,"base");
_tree Branch(1, "branch", &Base);
Base.subtrees.begin()->value = 8;
std::cout << Branch.value;
How would I make it so that Branch
& *Base.subtrees.begin()
refer to the same node? Or should i go the other way. Use add_branch()
to CREATE a branch/subtree?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
移动语义是关于移动对象的内部,而不是对象(作为一段类型的内存)本身。最好从值和不变量的角度来考虑它,因为即使考虑到移动,C++ 仍然具有值语义。这意味着:
换句话说,虽然您可以通过执行
std::move(*this)
将表达式*this
转换为右值,但是您现在无法实现您想要的效果因为std::list<_tree>
使用值语义,而_tree
本身也有值语义。*Base.subtrees.begin()
是与Branch
不同的对象,并且对前者的修改不会影响后者。如果您想要(或需要),请切换到引用语义,例如使用
std::shared_ptr<_tree>
和std::enable_shared_from_this
(然后您可以使用构造函数内的_root->add_branch(shared_from_this())
)。但我不推荐它,这可能会变得混乱。在我看来,值语义是非常理想的。通过值语义,使用树可能如下所示:
也就是说,addBranch 返回对新构造的节点的引用。在顶部撒上一些移动语义:
严格来说,如果
_tree
是可复制的移动语义,则不需要,但Base.addBranch(Tree);
也可以。Move semantics is about moving the internals of an object, not the object (as a typed piece of memory) itself. It's best to think about it in terms of values and invariants, since C++ still has value semantics even when moving is taken into account. This means:
In other words, while you can convert the expression
*this
to an rvalue by doingstd::move(*this)
what you want cannot be achieved right now sincestd::list<_tree>
uses value semantics and_tree
has value semantics itself.*Base.subtrees.begin()
is a distinct object fromBranch
and as things are modifications to the former won't affect the latter.Switch to reference semantics if that's what you want (or need), for instance by using
std::shared_ptr<_tree>
andstd::enable_shared_from_this
(you'd then use_root->add_branch(shared_from_this())
inside the constructor). I wouldn't recommend it though, this could get messy. Value semantics are very desirable in my opinion.With value semantics, using your tree could look like:
That is,
addBranch
returns a reference to the newly constructed node. Sprinkling some move semantics on top:Strictly speaking if
_tree
is copyable move semantics are not necessary though,Base.addBranch(Tree);
would work too.