0

在实现 BS 树时,我注意到了一些自从我开始使用 C++11 智能指针以来我不太确定的事情,这让我想知道为什么会这样。如果我使用init-brace 对{}而不是括号,则下面的代码可以正常工作;我个人的规则是初始化每个成员(直接或通过ctor),并且由于Node::rightNode::left都是智能指针,因此nullptr它是。 问题 1:为什么括号失败而 init-brace 对成功?仅在这种情况下,两者之间是否存在语义差异?

BST中,在采用 std::initializer_list 的 ctor 中,我知道 std::initializer_list 元素只能复制,根据this。因此,如果我没记错的话,根据最近 GN13 上的 Scott Meyer 的说法,对 const 对象执行移动只会触发对象的复制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

为什么括号失败而初始化大括号对成功?

因为括号用于函数声明。您不能使用它们在类范围内初始化变量。甚至int i(1);行不通。

为什么编译器无法在调用 BST::insert( T&& ) 时复制对象?

你的比较不公平。在您的auto版本中,您明确要求引用类型。在您的非auto版本中,您明确要求非引用类型。删除&&将使auto版本也可以工作。

你的insert方法需要一个T &&. 这是一个非const限定引用,因此它不能绑定到任何const对象。

auto &&被推论为const int &&,因为你不能改变 an 的内容initializer_list<int>:它的begin()end()方法返回const int *。添加std::move不起作用,您不能那样绕过const

auto将推断为int,并且会起作用:您将获得一个新的非const int局部变量i,其中包含初始化器列表中值的副本。您可以形成const对该局部变量的非引用。

于 2014-09-13T07:59:26.460 回答