首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >移动语义和引用语义

移动语义和引用语义
EN

Stack Overflow用户
提问于 2011-10-09 20:17:04
回答 1查看 214关注 0票数 2

我正在写一个树状的容器,其中每个“节点”都有一个带有分支/子树的列表,目前我的头看起来像:

代码语言:javascript
运行
复制
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中创建一棵树-但是这是如何使用调用的(忽略私有冲突)的:

代码语言:javascript
运行
复制
_tree Base(0,"base");
_tree Branch(1, "branch", &Base);
Base.subtrees.begin()->value = 8;
std::cout << Branch.value;

如何才能使Branch*Base.subtrees.begin()引用同一个节点?或者我应该走另一条路。是否使用add_branch()创建分支/子树?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-10-09 22:00:29

移动语义是关于移动对象的内部,而不是对象本身(作为一个类型化的内存)。最好从值和不变量的角度来考虑它,因为即使考虑到移动,C++仍然具有值语义。这意味着:

代码语言:javascript
运行
复制
std::unique_ptr<int> first(new int);
// invariant: '*this is either null or pointing to an object'
// current value: first is pointing to some int
assert( first != nullptr );

// move construct from first
std::unique_ptr<int> second(std::move(first));

// first and second are separate objects!
assert( &first != &second );

// New values, invariants still in place
assert( first == nullptr );
assert( second != nullptr );

// this doesn't affect first since it's a separate object
second.reset(new int);

换句话说,虽然您可以通过执行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()) )。不过,我不建议这样做,这可能会变得很混乱。在我看来,值语义是非常可取的。

对于值语义,使用树可能如下所示:

代码语言:javascript
运行
复制
_tree Base(0, "base");
auto& Branch = Base.addBranch(1, "branch");

也就是说,addBranch返回对新构造的节点的引用。在顶部散布一些移动语义:

代码语言:javascript
运行
复制
_tree Base(0, "base");
_tree Tree(1, "branch); // construct a node not connected to Base
auto& Branch = Base.addBranch(std::move(Tree));
// The node we used to construct the branch is a separate object
assert( &Tree != &Branch );

严格地说,如果_tree是可复制的,那么移动语义是不必要的,Base.addBranch(Tree);也可以工作。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7703427

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档