移动语义和引用语义
Move semantics and reference semantics
我正在写一个树状容器,其中每个"节点"都有一个带有分支/子树的列表,目前我的头看起来像:
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()
创建分支/子树?
Move语义是关于移动对象的内部,而不是对象本身(作为一个类型化的内存块)。最好从值和不变量的角度来考虑它,因为即使考虑了移动,c++仍然具有值语义。这意味着:
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())
)。但我不建议这么做,因为这会弄得一团糟。在我看来,值语义是非常可取的。
使用值语义,使用树可以像这样:
_tree Base(0, "base");
auto& Branch = Base.addBranch(1, "branch");
即,addBranch
返回对新构造的节点的引用。在顶部添加一些move语义:
_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);
也会工作。
相关文章:
- 何时在引用或唯一指针上使用移动语义
- 在C++17中,引用const字符串的语义应该是什么
- Xcode 语义问题引用或以前定义的代码
- 使用移动语义:右值引用作为方法参数
- <T>通过引用传输向量<shared_ptr>而不绕过共享语义
- C 移动语义:将唯一_ptr引用的矩阵附加到向量
- 我应该如何确保对移动构造函数的调用?(移动语义和右值引用)
- C/C++ 函数中的引用、指针或值语义
- 在超载算术中移动语义和传递引用
- 移动语义和常量引用
- 有人能解释一下这些编程术语吗:引用语义,非线性可变状态
- 如果右值没有绑定到const引用,这将如何影响移动语义和完美转发
- 使用 LValue 引用移动语义
- C++Rvalue引用和移动语义
- 通过移动语义和右值引用改进了性能
- 如何使用boost::expression-static在语义操作中引用可选子匹配
- 引用的c++ const语义
- 移动语义和引用语义
- 共享内存和写时复制或右值引用和移动语义
- range-v3 的"partial_sum"如何不与非拥有引用语义相矛盾?