标签:
http://blog.csdn.net/cpd92/article/details/50651700
http://www.tuicool.com/articles/i2qyyyB
move 就是右值引用,减少了copy和释放的过程,提高了程序性能。
#include <iostream> #include <string> #include<vector> using namespace std; class MyString { private: char* _data; size_t _len; void _init_data(const char *s) { _data = new char[_len + 1]; memcpy(_data, s, _len); _data[_len] = ‘\0‘; } public: MyString() { _data = NULL; _len = 0; } MyString(const char* p) { _len = strlen(p); _init_data(p); } MyString(const MyString& str) { _len = str._len; _init_data(str._data); std::cout << "Copy Constructor is called! source: " << str._data << std::endl; } MyString& operator=(const MyString& str) { if (this != &str) { _len = str._len; _init_data(str._data); } std::cout << "Copy Assignment is called! source: " << str._data << std::endl; return *this; } virtual ~MyString() { if (_data) free(_data); } }; int main() { MyString a; a = MyString("Hello"); std::vector<MyString> vec; vec.push_back(MyString("World")); }
在 main 函数中,实现了调用拷贝构造函数的操作和拷贝赋值操作符的操作。MyString(“Hello”) 和 MyString(“World”) 都是临时对象,也就是右值。虽然它们是临时的,但程序仍然调用了拷贝构造和拷贝赋值,造成了没有意义的资源申请和释放的操作。如果能够直接使用临时对象已经申请的资源,既能节省资源,有能节省资源申请和释放的时间。这正是定义转移语义的目的。
增加转移构造,转移赋值运算符重载
MyString(MyString&& str) { std::cout << "Move Constructor is called! source: " << str._data << std::endl; _len = str._len; _data = str._data; str._len = 0; str._data = NULL; } MyString& operator=(MyString&& str) { std::cout << "Move Assignment is called! source: " << str._data << std::endl; if (this != &str) { _len = str._len; _data = str._data; str._len = 0; str._data = NULL; } return *this; }
增加了转移构造函数和转移复制操作符后,我们的程序运行结果为 :
Move Assignment is called! source: Hello Move Constructor is called! source: World
左值右值判断
#include <iostream> #include <string> #include<vector> using namespace std; template<typename T> void PrintT(T& t) { cout << "lvaue" << endl; } template<typename T> void PrintT(T && t) { cout << "rvalue" << endl; } template<typename T> void TestForward(T && v) { PrintT(v); PrintT(std::forward<T>(v)); PrintT(std::move(v)); } int main () { TestForward(1); int x = 1; TestForward(x); TestForward(std::forward<int>(x)); }
std::forward会按参数原来的类型转发
std::move 转为右值
万能包装器
#include <iostream> #include <string> #include<vector> using namespace std; template<class Function, class... Args> inline auto FuncWrapper(Function && f, Args && ... args) -> decltype(f(std::forward<Args>(args)...)) { return f(std::forward<Args>(args)...); } void test0() { cout << "void" << endl; } int test1() { return 1; } int test2(int x) { return x; } string test3(string s1, string s2) { return s1 + s2; } void test() { FuncWrapper(test0); //没有返回值,打印1 cout<<FuncWrapper(test1)<<endl; //返回1 cout<<FuncWrapper(test2, 1)<<endl; //返回1 cout<<FuncWrapper(test3, "aa", "bb")<<endl; //返回"aabb" } int main() { test(); }
c++11中大部分容器都加了一个emplace_back成员函数,vector中它的定义是这样的:
template< class... Args >
void emplace_back( Args&&... args );
这里的Args&&是一个未定的引用类型,因此它可以接收左值引用和右值引用,它的内部也是调用了std::forward实现完美转发的。因此如果我们需要往容器中添加右值、临时变量时,用emplace_back可以提高性能。
标签:
原文地址:http://www.cnblogs.com/yuguangyuan/p/5860626.html