左值与右值
左值我们直接可以控制的值 可以直接或者间接访问(合法)其的内存地址
右值我们无法直接或者间接访问其的内存地址
s t d : : m o v e ( ) std::move() std::move()
为什么需要引入 s t d : : m o v e ( ) std::move() std::move()
请参考下面一个例子
#include <cstdio>
#include <cstring>
using namespace std;
class string
{
private:
char * data;
int data_size;
public:
string(const char* s)
{
printf("construct\n");
data_size = strlen(s);
data = new char[data_size];
memcpy(data, s, data_size);
}
~string()
{
delete data;
}
string(const string& a)
{
printf("copy\n");
data_size = a.data_size;
data = new char[data_size];
memcpy(data, a.data, data_size);
}
void print()
{
printf("%s", data);
}
};
class Man
{
private:
string name;
public:
Man(const string& a):
name(a)
{
}
void print()
{
name.print();
}
};
int main()
{
Man s("湖人总冠军!");
s.print();
return 0;
}
在这种情况下 内存将会两次分配 并移动两次 这是我们完全不需要的 因此引入 s t d : : m o v e ( ) std::move() std::move()以及右值引用
但一个值是一个右值----代表它的值无关紧要 仅仅是一些参数 被改变了也没有什么关系
于是我们可以直接将右值的值 赋予 声明的变量 减少一次内存分配 具体代码如下
#include <cstdio>
#include <cstring>
#include <algorithm>
class string
{
private:
char * data;
int data_size;
public:
string() = default;
string(const char* s)
{
printf("construct\n");
data_size = strlen(s);
data = new char[data_size+1];
memcpy(data, s, strlen(s)+1);
}
~string()
{
delete data;
}
string(const string& a)
{
printf("copy\n");
data_size = a.data_size;
data = new char[data_size+1];
memcpy(data, a.data, data_size+1);
}
string(string && a)
{
printf("Move!\n");
data_size = a.data_size;
data = a.data;
a.data_size = 0;
a.data = NULL;
}
string& operator =(const string& a)
{
printf("copy\n");
data_size = 0;
delete data;
data_size = a.data_size;
data = new char[data_size + 1];
memcpy(data, a.data, data_size + 1);
return *this;
}
string& operator =(string &&a)
{
if (data == a.data)return*this;
data_size = 0;
delete data;
data_size = a.data_size;
data = a.data;
a.data = NULL;
a.data_size = 0;
return *this;
}
void print()
{
printf("%s\n", data);
}
};
class Man
{
private:
string name;
public:
Man() = default;
Man(const string& a):
name(a)
{
}
Man(string && a) :
name(std::move(a))
{
}
void print()
{
name.print();
}
};
int main()
{
Man s("湖人总冠军!");
Man p;
s.print();
p.print();
printf("\n");
p = s;
s.print();
p.print();
printf("\n");
p = std::move(s);
s.print();
p.print();
return 0;
}
//看看std::move()源代码
//这个函数的本质就是 static_cast<remove_reference_t<_Ty>&&>(_Arg) 转化为 _Ty && 右值引用
template<class _Ty>
_NODISCARD constexpr remove_reference_t<_Ty>&&
move(_Ty&& _Arg) noexcept
{ // forward _Arg as movable
return (static_cast<remove_reference_t<_Ty>&&>(_Arg));
}
注意:
尽管move()可以提高效率 但是也要注意情形 而不能乱用