[英]Binding const rvalue to rvalue reference
While implementing a BS Tree, I noticed some things that I wasn't so sure about since I started using C++11 smart pointers and it makes me wonder why it is so. 在实现BS树时,由于我开始使用C ++ 11智能指针,我注意到了一些不确定的事情,这让我想知道为什么会这样。 The code below works fine if I use init-brace pairs{} instead of the parentheses;
如果我使用init-brace pair {}而不是括号,则下面的代码可以正常工作; my personal rule is to value initialize every member(directly or through a ctor) and since Node::right and Node::left are both smart pointers, therefore, nullptr it is.
我个人的规则是(直接或通过ctor)对每个成员进行值初始化,并且由于Node :: right和Node :: left都是智能指针,因此, nullptr是。 Question 1 : Why does the parentheses fail and init-brace pairs succeed?
问题1 :为什么括号会失败,而括号对会成功? In this case ONLY, is there any semantic difference between the two?
仅在这种情况下,两者之间在语义上有什么区别吗?
In BST , in the ctor that takes an std::initializer_list, I understand that std::initializer_list elements are only copyable, according to this . 在BST,在其采用的std :: initializer_list的构造函数,我明白的std :: initializer_list元素仅可复制,根据这个 。 So if I'm not wrong, according to Scott Meyer at the recent GN13, performing a move on a const object would only trigger the copy-ctor of the object.
因此,根据最近的GN13的斯科特·迈耶(Scott Meyer)的说法,如果我没记错,对const对象执行移动只会触发该对象的copy-ctor。
Quesion 2 Why does the compiler fail to copy the object at the call to BST::insert( T&& ) ? 问题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;
}
Why does the parentheses fail and init-brace pairs succeed?
为什么括号会失败,而括号对会成功?
Because parentheses are used for function declarations. 因为括号用于函数声明。 You cannot use them to initialise variables at class scope.
您不能使用它们在类范围内初始化变量。 Even
int i(1);
甚至
int i(1);
won't work. 将无法正常工作。
Why does the compiler fail to copy the object at the call to BST::insert( T&& ) ?
为什么编译器在调用BST :: insert(T &&)时无法将对象复制?
You're not being fair in your comparison. 您的比较不公平。 In your
auto
version, you explicitly ask for a reference type. 在
auto
版本中,您明确要求引用类型。 In your non- auto
version, you explicitly ask for a non-reference type. 在非
auto
版本中,您明确要求提供非引用类型。 Removing the &&
would make the auto
version work too. 删除
&&
也会使auto
版本正常工作。
Your insert
method takes a T &&
. 您的
insert
方法采用T &&
。 That's a non- const
-qualified reference, so it cannot bind to any const
object. 那是一个非
const
限定的引用,因此它不能绑定到任何const
对象。
auto &&
is deduced to const int &&
, because you cannot change the contents of an initializer_list<int>
: its begin()
and end()
methods return const int *
. auto &&
被推导为const int &&
,因为您不能更改initializer_list<int>
的内容:它的begin()
和end()
方法返回const int *
。 Adding std::move
doesn't work, you cannot bypass const
like that. 添加
std::move
无法正常工作,您不能像这样绕过const
。
auto
would deduce to int
, and would work: you'd get a fresh non- const
int
local variable i
, containing a copy of the value in the initialiser list. auto
可以推断为int
,并且可以工作:您将获得一个新鲜的非const
int
局部变量i
,其中包含初始化程序列表中值的副本。 You can form non- const
references to that local variable. 您可以形成对该局部变量的非
const
引用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.