2

各「ノード」にブランチ/サブツリーのリストがあるツリーのようなコンテナーを作成しています。現在、私の頭は次のようになっています。

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(???)
}

これで、2 番目のコンストラクターが内部にツリーを作成しますが、_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()ブランチ/サブツリーの作成に使用しますか?

4

1 に答える 1

3

移動セマンティクスは、オブジェクト自体ではなく、オブジェクトの内部を移動することです。移動を考慮しても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);

つまり、値セマンティクスを使用し、それ自体に値セマンティクスがあるため、必要な処理を実行して式*thisを右辺値に変換することはできますが、std::move(*this)現時点では実現できません。は別のオブジェクトであり、前者を変更しても後者には影響しません。std::list<_tree>_tree*Base.subtrees.begin()Branch

std::shared_ptr<_tree>たとえば、 andを使用してstd::enable_shared_from_this_root->add_branch(shared_from_this())コンストラクター内で使用する)、それが必要な場合(または必要な場合)は、参照セマンティクスに切り替えます。私はそれをお勧めしませんが、これは厄介になる可能性があります。私の意見では、値のセマンティクスは非常に望ましいものです。


値のセマンティクスでは、ツリーの使用は次のようになります。

_tree Base(0, "base");
auto& Branch = Base.addBranch(1, "branch");

つまりaddBranch、新しく構築されたノードへの参照を返します。いくつかの移動セマンティクスを上に振りかける:

_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);機能します。

于 2011-10-09T14:00:28.547 に答える