v******y 发帖数: 84 | 1 这是我的理解,不对的请指出,谢谢
The usage of rvalue reference &&
Define a class
class MyClass{
public:
MyClass(){/*require for const MyClass cMyClass init. Without this default
constructor, const MyClass will have to be declared and defined as such:
const MyClass cMyClass=MyClass(). MyClass() here will call synthesized
constructor automatically generated by compiler. This synthesized
constructor can not directly initiate const. So following is illegal without
default constructor: const MyClass cMyClass;*/}
};
//define three overload function
void foo(MyClass &&){
std::cout<<"MyClsss&&"<
}//only binds to rvalue
void foo(MyClass &){
std::cout<<"MyClsss&"<
}//only binds to lvalue. Can not refer to rvalue
void foo(const MyClass &){
std::cout<<"const MyClsss&"<
}//binds to lvalue and rvlalue with low level const
call your overload function
foo(MyClass());//MyClass() is a temporary unnamed variable, call rvalue foo(
MyClass&&)
MyClass myClass;//init a named lvalue myClass on stack
foo(myClass);//call lvalue foo(MyClass&)
const MyClass cMyClass; ;//init a named const lvalue myClass on stack
foo(cMyClass);//call const lvalue foo(cosnt MyClass&)
If you don’t define rvalue foo(MyClass &&), foo(MyClass()) can call foo
function with const lvalue parameters, foo(const MyClass &). It can not
call foo(MyClass&).
The reason is that initiation of parameter is equal to variable initiation.
It can not reference a literal or unnamed temporary rvalue object. Following
initiation of variable ref_obj is illegal.
MyClass &ref_obj=MyClass();//can not reference to a rvalue object
Const reference can refer to literals and rvalue object:
const MyClass &ref_obj=MyClass();//legal
foo(ref_obj);//call foo(const MyClass&)
Examples on literal
void bar ( int &){
std::cout<<"int &"<
}
void bar (const int &){
std::cout<<"const int &"<
}
bar(10) call bar(cons tint &) not bar(int &)
void poo(std::string &){
std::cout<<"string &"<
}
void poo(const std::string &){
std::cout<<"const string &"<
}
poo("C++ rocks!");//calls poo(const std::string &) NOT poo(std::string&)
However, if we use rvalue reference, literals can be refer by &&
Define:
void poo(std::string &&){
std::cout<<"string &&"<
}
poo("C++ rocks!");//it will call void poo(std::string &&). Without it , it
will call poo(const std::string&).
Note: for rvalue, it is default const, so std::string &&=const std::string &&
Then you wonder what will happen if you define a foo function with copy
initiation (not reference) as follows.
void foo(MyClass){
std::cout<<"MyClsss"<
}
For function with copy initiation, you can not overload with a top level
const.
This is because top level const is ignored during type matching. It looks
same to the compiler.
void foo(const MyClass){
std::cout<<"const MyClsss"<
} //redefine foo (MyClass) can not overload
So you can only choose one. And following are able to call foo(MyClass)
foo(MyClass());//rvalue
MyClass myClass;
foo(myClass);//lvalue
const MyClass cMyClass;
foo(cMyClass);//const lvalue. Top level const is ignored in initiation
Following is very confusing. Foo copy initiation can be overloaded with foo
reference version. But usage will be ambiguous and cause compiler error.
It is no problem to define
void foo(MyClass){
std::cout<<"MyClsss"<
}//MyClass can binds to lvalue and rvalue
void foo(const MyClass &&){
std::cout<<"MyClsss&&"<
}//only binds to rvalue
void foo(MyClass &){
std::cout<<"MyClsss&"<
}//binds to lvalue of course rvlalue
void foo(const MyClass &){
std::cout<<"const MyClsss&"<
}//binds to lvalue of course rvlalue with low level const
IF you call
foo(MyClass());//Compiler can not decide to call rvalue foo(MyClass&&) or
copy version foo(MyClass)
//It is equivalent
It is also true for the following
MyClass myClass;
foo(myClass);//ambiguous
const MyClass cMyClass;
foo(cMyClass);// ambiguous |
|