版权声明:guojawee https://blog.csdn.net/weixin_36750623/article/details/84852947
本文涉及的概念:
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();
}