0

BS ツリーを実装しているときに、C++11 スマート ポインターを使い始めて以来、よくわからないことがいくつかあることに気付きました。以下のコードは、括弧の代わりにinit-brace のペア{}を使用すると正常に動作します。私の個人的なルールは、すべてのメンバーを (直接または ctor を介して) 値を初期化することです。Node ::rightNode::leftはどちらもスマート ポインターであるため、nullptrです。 質問 1 : 括弧が失敗し、init-ブレースのペアが成功するのはなぜですか? この場合のみ、両者の間に意味上の違いはありますか?

BSTでは、std::initializer_list を受け取る ctor で、this によると、std::initializer_list 要素はコピーのみ可能であることがわかりまし。したがって、私が間違っていなければ、最近の GN13 での Scott Meyer によると、const オブジェクトで移動を実行すると、オブジェクトの copy-ctor のみがトリガーされます。

質問 2 BST::insert( T&& )の呼び出しでコンパイラがオブジェクトのコピーに失敗するのはなぜですか?

#include <memory>

template<typename T>
struct Node
{

    //~ std::unique_ptr<Node<T>> left ( nullptr ), right ( nullptr );
    std::unique_ptr<Node<T>> left { nullptr }, right { nullptr };
    Node<T> *parent = nullptr;
    T value { };
    Node<T> () = default;
    Node<T> ( T && val, Node<T> * _left = nullptr, Node<T> *_right = nullptr,
          Node<T> *_parent = nullptr ): left( _left ), right ( _right ), parent( _parent ),
                                        value ( std::move( val ) )
        {

        }
};
template<typename T>
struct BinarySearchTree
{
    std::unique_ptr<Node<T>> root;

    BinarySearchTree(): root { nullptr } { }
    BinarySearchTree( std::initializer_list<T> && lst ): BinarySearchTree { }{
    //If the below code were changed to
    //~ for( auto && i: lst ){ it would be an error
        for( typename std::remove_reference<typename std::remove_const<T>::type>::type i: lst ){
            this->insert( std::move( i ) );
        }
    }
    void insert( T && v ) { }
};

int main(){
    BinarySearchTree<int> a { 11, 24 };

    return 0;
}
4

1 に答える 1

3

括弧が失敗し、init-ブレースのペアが成功するのはなぜですか?

関数宣言に括弧が使われているためです。これらを使用して、クラス スコープで変数を初期化することはできません。うまくint i(1);いきません。

BST::insert( T&& ) の呼び出しでコンパイラがオブジェクトのコピーに失敗するのはなぜですか?

あなたはあなたの比較において公平ではありません。あなたのautoバージョンでは、参照型を明示的に要求します。非autoバージョンでは、非参照型を明示的に要求します。を削除する&&と、autoバージョンも機能します。

あなたのinsertメソッドはT &&. これはconst修飾されていない参照であるため、どのconstオブジェクトにもバインドできません。

auto &&の内容を変更するconst int &&ことはできないため、と推定されinitializer_list<int>ます。追加は機能しません。そのようにバイパスすることはできません。begin()end()const int *std::moveconst

autoと推測し、機能します。初期化リストの値のコピーを含む、int新しい非const intローカル変数を取得します。そのローカル変数へのi非参照を形成できます。const

于 2014-09-13T07:59:26.460 に答える