大家都开始C++0x了,我也来凑热闹,今天的主题是《调侃rvalue-reference》
和所有的故事一样,先来一个起因。
话说从C到C++,都有左值和右值的概念,来满足语义的需要。这与变量/对象无关,是用来解释一个表达式的类型。
int foo();int *p = &foo(); //#1p = &1; //#2
int &a = 0; //错误const int &b = 0; //正确
class T{public: T():i(0){} T& set() { i = 5; return *this; } int value() const { return i; }private: int i;};int x = T().set().value();int & r = int();r = 5; //r引用的临时对象已经失效了,分号之后就已经销毁了。const int &cr = int();int x = cr;
std::auto_ptr<int> a(new int);std::auto_ptr<int> b = a;
std::auto_ptr<int> foo(){ return std::auto_ptr<int>(new int);}std::auto_ptr<int> p = foo();template<typename T>class auto_ptr{public: auto_ptr(const auto_ptr& other) throw() :ptr(other.safe_release()) {} auto_ptr& operator=(const auto_ptr& other) throw();private: T* safe_release() const throw() { T * ret = ptr; ptr = 0; return ret; }private: T * mutable ptr;};template<typename T>class auto_ptr{public: auto_ptr(auto_ptr& other) throw(); auto_ptr(auto_ptr_ref ref) throw(); auto_ptr& operator=(auto_ptr& other) throw(); auto_ptr& operator=(auto_ptr_ref ref) throw(); ...};int foo();const int cfoo();int &&r = foo();const int &&cr = cfoo();//同样,也能绑定左值。int i;int &&r = i;const int ci;const int&& cr = ci;
int &&r = 0; //r被当作左值看待。int&& foo();foo(); //foo的返回类型是右值引用,其仍然是右值。
class T{public: T():p(new int){} T(T& t) :p(t.p) { t.p = 0; } T& operator=(T& t) { if(this != &t) { delete p; p = t.p; t.p = 0; } return *this; }private: int *p;};T a;T b(a);T c;c = b;std::vector<std::string> v;
template < class CharType, class Traits=char_traits<CharType>, class Allocator=allocator<CharType>>class basic_string{public: basic_string(const basic_string& _Right, size_type _Roff = 0, size_type _Count = npos, const allocator_type& _Al = Allocator ( ) ); //拷贝构造函数 basic_string(basic_string&& _Right, size_type _Roff = 0, size_type _Count = npos, const allocator_type& _Al = Allocator ( ) ); //转移构造函数 basic_string& operator=(const basic_string&); //拷贝赋值操作符 basic_string& operator=(basic_string&&); //转移赋值操作符};std::string foo(){ return "Hello, World";}std::string str;str = foo(); //没有了字符串的拷贝动作。class T{public: T(const T& other) //拷贝构造 :text(other.text) {} T(T&& other) //转移构造 :text(other.text) {} T& operator=(const T& other) //拷贝赋值操作符 { if(this != &other) { text = other.text; } return *this; } T& operator=(T&& other) //转移赋值操作符 { if(this != &other) { text = other.text; } return *this; }private: std::string text;}; T(T&& other) //转移构造 :text(other.text) //调用拷贝构造函数 {} T& operator=(T&& other) //转移赋值操作符 { if(this != &other) { text = other.text; //调用拷贝赋值操作符 } return *this; }
namespace std{ template <typename T> typename remove_reference<T>::type&& move(T&& a) { return a; }} T(T&& other) //转移构造 :text(std::move(other.text)) {} T& operator=(T&& other) //转移赋值操作符 { if(this != &other) { text = std::move(other.text); } return *this; }class window{//...};template<typename Window>window* factory(){ return (new Window);}window* w = factory<Window>();class msg_window :public window{public: msg_window(const std::string& text);};class input_window : public window{public: input_window(std::string& text);};factory就会写成template<typename Window, typename T>window* factory(const T&);和template<typename Window, typename T>window* factory(T&);namespace std{ template<typename T> struct identity { typedef T type; }; template<typename T> T&& forward(typename identity<T>::type&& t) { return t; }}template<typename Window, typename T>window* factory(T&& t){ return (new Window(std::forward<T>(t)));}window *msg = factory<msg_window>(std::string("Hello"));std::string text;window *input = factory<input_window>(text);template<typename T>void f(T&& t);int i;f(i); //#1f(2); //#2
template<typename T>T&& forward(T&& t){ return t;}template<typename Window, typename T>window* factory(T&& t){ return (new Window(std::forward(t)));}
class test_window : public window{public: test_window(const std::string&); test_window(std::string&);};factory<test_window>(std::string("Hello"));template<typename Window, typename T>window* factory(T&& t){ return (new Window(std::forward<T>(t)));}std::string text;factory<test_window>(text); //#1factory<test_window>(std::string("Hello")); //#2