C++ 将常量右值绑定到右值引用
在实现BS树的过程中,我注意到了一些我从开始使用C++11智能指针开始就不太确定的事情,这让我想知道为什么会这样。如果我使用init大括号对{}而不是括号,下面的代码就可以正常工作;我个人的规则是对每个成员进行值初始化(直接或通过一个ctor),因为Node::right和Node::left都是智能指针,所以它是空指针。 问题1:为什么括号失败而初始大括号对成功?仅在这种情况下,两者之间是否存在语义差异 在BST中,在接受std::initializer\u列表的ctor中,我知道std::initializer\u列表元素只能复制,根据。因此,如果我没有错的话,根据Scott Meyer在最近的GN13上的说法,对const对象执行移动只会触发该对象的复制 问题2为什么编译器在调用BST::insert(T&&)时无法复制对象C++ 将常量右值绑定到右值引用,c++,c++11,smart-pointers,pass-by-rvalue-reference,C++,C++11,Smart Pointers,Pass By Rvalue Reference,在实现BS树的过程中,我注意到了一些我从开始使用C++11智能指针开始就不太确定的事情,这让我想知道为什么会这样。如果我使用init大括号对{}而不是括号,下面的代码就可以正常工作;我个人的规则是对每个成员进行值初始化(直接或通过一个ctor),因为Node::right和Node::left都是智能指针,所以它是空指针。 问题1:为什么括号失败而初始大括号对成功?仅在这种情况下,两者之间是否存在语义差异 在BST中,在接受std::initializer\u列表的ctor中,我知道std::i
#包括
模板
结构体类型
{
//~std::unique_ptr left(nullptr),right(nullptr);
std::unique_ptr left{nullptr},right{nullptr};
节点*parent=nullptr;
T值{};
Node()=默认值;
节点(T&&val,节点*_left=nullptr,节点*_right=nullptr,
节点*_parent=nullptr):左(_left)、右(_right)、父(_parent),
值(标准::移动(val))
{
}
};
模板
结构二进制搜索树
{
std::唯一的_ptr根;
BinarySearchTree():根{nullptr}{}
BinarySearchTree(std::initializer_list&&lst):BinarySearchTree{}{
//如果以下代码更改为
//~for(auto&&i:lst){这将是一个错误
对于(typename std::remove_reference::type i:lst){
这->插入(std::move(i));
}
}
无效插入(T&v){}
};
int main(){
二元搜索树a{11,24};
返回0;
}
为什么括号失败而init括号对成功
因为圆括号用于函数声明。不能使用圆括号在类范围内初始化变量。即使inti(1);
也不起作用
为什么编译器在调用BST::insert(T&&)时复制对象失败
你的比较不公平。在自动
版本中,你明确要求引用类型。在非自动
版本中,你明确要求非引用类型。删除&&
将使自动
版本也起作用
您的insert
方法采用T&
。这是一个非const
限定引用,因此它不能绑定到任何const
对象
auto&&
被推断为const int&
,因为您无法更改初始值设定项列表的内容:它的begin()
和end()
方法返回const int*
。添加std::move
不起作用,您不能像这样绕过const
auto
将推断为int
,并将起作用:您将获得一个新的非const
int
局部变量i
,其中包含初始化器列表中值的副本。您可以对该局部变量形成非const
引用
为什么括号失败而init括号对成功
因为圆括号用于函数声明。不能使用圆括号在类范围内初始化变量。即使inti(1);
也不起作用
为什么编译器在调用BST::insert(T&&)时复制对象失败
你的比较不公平。在自动
版本中,你明确要求引用类型。在非自动
版本中,你明确要求非引用类型。删除&&
将使自动
版本也起作用
您的insert
方法采用T&
。这是一个非const
限定引用,因此它不能绑定到任何const
对象
auto&&
被推断为const int&
,因为您无法更改初始值设定项列表的内容:它的begin()
和end()
方法返回const int*
。添加std::move
不起作用,您不能像这样绕过const
auto
将推断为int
,并将起作用:您将获得一个新的非const
int
局部变量i
,其中包含初始化器列表中值的副本。您可以对该局部变量形成非const
引用
为什么括号失败而init括号对成功
因为圆括号用于函数声明。不能使用圆括号在类范围内初始化变量。即使inti(1);
也不起作用
为什么编译器在调用BST::insert(T&&)时复制对象失败
你的比较不公平。在自动
版本中,你明确要求引用类型。在非自动
版本中,你明确要求非引用类型。删除&&
将使自动
版本也起作用
您的insert
方法采用T&
。这是一个非const
限定引用,因此它不能绑定到任何const
对象
auto&&
被推断为const int&
,因为您无法更改初始值设定项列表的内容:它的begin()
和end()
方法返回const int*
。添加std::move
不起作用,您不能像这样绕过const
auto
将推断为int
,即
#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;
}