C++11之右值引用、移動語義
本文涉及的概念:
1. 右值引用
2. std::move
3. 移動建構函式、移動賦值函式
右值引用的主要目的之一是實現移動語義。
1、為什麼使用移動語義?
避免拷貝帶來的開銷
2、std::move
功能:將引數從左值變成右值,使得引數為左值時呼叫移動語義的函式來避免開銷
詳細解釋:因為傳遞的引數如果是左值,將會呼叫拷貝構造、拷貝賦值函式,但是使用std::move將引數轉換成右值後,將會呼叫移動拷貝構造、移動賦值函式。
3、示例程式碼
看程式碼可以看到:
① 移動建構函式、移動賦值函式:進行深拷貝,在賦值
② 拷貝建構函式、拷貝賦值函式:轉換所有權,不經過拷貝
那麼是呼叫移動語義的函式?還是呼叫拷貝語義的函式?
編譯器會判斷傳入引數是左值?還是右值?,呼叫相對應的函式;當想讓傳入左值時,呼叫移動語義的函式,先使用std::move將左值轉換成右值。
/*
右值引用的主要目的:移動語義,將b的控制權轉交給a
避免拷貝過程帶來的開銷,提高效率
*/
#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include<iostream>
#include<vector>
using namespace std;
class MyString{
public:
MyString();
MyString(int len);
MyString(const char* str);
~MyString();
public:
MyString(const MyString& another); //預設拷貝構造
MyString& operator=(const MyString& another);//預設賦值
public:
MyString(MyString&& another); //移動拷貝構造
MyString& operator=(MyString&& ano);//移動賦值
public://運算子過載
MyString operator+(const MyString& another);
MyString& operator+=(const MyString& another);
bool operator==(const MyString& another);
bool operator!=(const MyString& another);
char& operator[](int index);
friend ostream& operator<<(ostream& cout, const MyString& myStr);
friend istream& operator>>(istream& cin, MyString& myStr);
private:
int len;
char* str;
};
MyString::MyString(){
cout << "建構函式" << endl;
this->len = 0;
this->str = NULL;
}
MyString::MyString(int len){
cout << "建構函式" << endl;
this->len = len;
this->str = new char[len + 1];
memset(this->str, 0, sizeof(this->str));
}
MyString::MyString(const char* str){
cout << "建構函式" << endl;
if (str == NULL){
this->len = 0;
this->str = new char[0 + 1];
this->str = '\0';
}
this->len = strlen(str);
this->str = new char[this->len + 1];
strcpy(this->str, str);
}
MyString::~MyString(){
cout << "解構函式" << endl;
if (this->str != NULL){
delete[] this->str;
this->str = NULL;
this->len = 0;
}
}
MyString::MyString(const MyString& another){
cout << "預設拷貝構造" << endl;
this->len = another.len;
this->str = new char[this->len + 1];
strcpy(this->str, another.str);
}
MyString& MyString::operator=(const MyString& another){
cout << "預設賦值" << endl;
if (this != &another){//判斷拷貝自身
if (this->str != NULL)//釋放自身垃圾
delete[] this->str;
//深拷貝
this->str = new char[another.len + 1];
strcpy(this->str, another.str);
this->len = another.len;
}
return *this;//返回物件本身
}
MyString::MyString(MyString&& another){
cout << "移動拷貝構造" << endl;
//ano.str的控制權轉移給this->str
this->str = another.str;
another.str = NULL;
}
MyString& MyString::operator=(MyString&& ano){
cout << "移動賦值" << endl;
if (this != &ano){
if (this->str != NULL)
delete this->str;
//ano.str的控制權轉移給this->str
this->str = ano.str;
ano.str = NULL;
}
return *this;
}
MyString MyString::operator+(const MyString& another){
char* tmp = this->str; //臨時變數指向this
this->len += another.len;
this->str = new char[this->len + 1];
strcpy(this->str, tmp);
strcat(this->str, another.str);
if (tmp != NULL){
delete tmp;
tmp = NULL;
}
return *this;
}
MyString& MyString::operator+=(const MyString& another){
char* tmp = this->str; //臨時變數指向this
this->len += another.len;
this->str = new char[this->len + 1];
strcpy(this->str, tmp);
strcat(this->str, another.str);
if (tmp != NULL){
delete tmp;
tmp = NULL;
}
return *this;
}
bool MyString::operator==(const MyString& another){
return strcmp(this->str, another.str);
}
bool MyString::operator!=(const MyString& another){
return !strcmp(this->str, another.str);
}
char& MyString::operator[](int index){//注意返回值char&
if (index > this->len)//索引越界判斷
exit(-1);
else
return this->str[index];
}
ostream& operator<<(ostream& cout, const MyString& myStr){
cout << myStr.str;
return cout;
}
istream& operator>>(istream& cin, MyString& myStr){
//1.釋放myStr之前的字串
if (myStr.str != NULL){
delete[] myStr.str;
myStr.str = NULL;
myStr.len = 0;
}
//2.通過cin新增新的字串
char buf[4096] = { 0 };
cin >> buf;
myStr.len = strlen(buf);
myStr.str = new char[myStr.len + 1];
strcpy(myStr.str, buf);
return cin;
}
void test01(){
MyString st1("ABC");
MyString st2(st1);
MyString st3(std::move(st1));
}
void test02(){
MyString a("11");
MyString b("22");
a = b;
a = std::move(b);
}
int main(){
test01();
test02();
}
相關文章
- [c++11]我理解的右值引用、移動語義和完美轉發C++
- 右值引用,移動語義,完美轉發
- 對C++11中的`移動語義`與`右值引用`的介紹與討論C++
- C++11 左值引用和右值引用與引用摺疊和完美轉發C++
- C++11中std::move、std::forward、左右值引用、移動建構函式的測試C++Forward函式
- [CPP] 左值 lvalue,右值 rvalue 和移動語義 std::move
- 深入理解移動語義
- 透徹理解C++11新特性:右值引用、std::move、std::forwardC++Forward
- 左值、左值引用、右值、右值引用
- ABAP 程式語言裡的 Reference Semantic - 引用語義
- C++左值引用與右值引用C++
- C++ 右值引用和左值引用C++
- c++ 左值引用與右值引用C++
- 左值、右值、左值引用,右值引用,std::move函式函式
- 右值引用
- C++移動語義 詳細講解【Cherno C++教程】C++
- 使用 ref 引用值
- C++ 左值引用和右值引用之間的轉換C++
- C++右值引用C++
- PyQt5 之右鍵選單QT
- Go語言引數傳遞是傳值?還是傳引用 ?Go
- 您知道移動OA價值所在
- 在 C 中引用匯編語言定義的 .globl 變數變數
- C++11新特性(一):語言特性C++
- C++11新特性(三):語言特性C++
- C++11新特性(二):語言特性C++
- C++11的一些語法C++
- go語言引數傳遞到底是傳值還是傳引用Go
- Qt自定義動畫插值函式QT動畫函式
- RN自定義元件封裝 - 神奇移動元件封裝
- 值傳遞和引用傳遞
- 值型別和引用型別型別
- GO切片傳值/引用/指標Go指標
- javascript原始值和引用值型別及區別JavaScript型別
- 常被新手忽略的值賦值和引用賦值(偏redux向)賦值Redux
- C#程式設計引用型別和值型別 以及引用傳遞和值傳遞C#程式設計型別
- C#7.0--引用返回值和引用區域性變數C#變數
- JavaScript值型別和引用型別JavaScript型別