目录意义左值右值值类别左值纯右值将亡值左值引用右值引用std::move()移动构造&移动赋值运算符重载测试&验证意义 充分利用临时对象,避免拷贝。 左值右值 值类别
充分利用临时对象,避免拷贝。
在 c++11之后,C++根据
将值分为以下类别:
泛左值:被标识
右值:可移动
int a = 1;
a是一个左值,左值是关联了名称的内存位置。
int a = 1;
1是一个纯右值,纯右值是指不被标识且可移动的值,例如字面量。
using std::string;
string get()
{
string ret = "abc";
return ret;
}
string str = get();
get() 函数调用会产生一个临时变量赋给str,这个临时变量是将亡值,此时的赋值是移动语义(c++11之前是复制语义)。
int a = 1;
int& a_lref = a;
a_lref是左值引用
int&& rref = 1;
rref是右值引用(rref是类型为右值引用的左值)
void foo(int&& rref)
{
}
int a = 1;
foo(std::move(a));
std::move本质是类型转换,即把左值转换成右值
注意:被转换的对象不应再被使用,否则结果难以预计(通常内存会被转移)
class Foo
{
public:
Foo()
{
m_data = malloc(32);
}
Foo(const Foo& rhs)
{
if(m_data == nullptr)
{
m_data = malloc(32);
}
memcopy(m_data,rhs.m_data,32);
}
Foo& operator = (const Foo& rhs)
{
if(m_data == nullptr)
{
m_data = malloc(32);
}
memcopy(m_data,rhs.m_data,32);
return *this;
}
Foo(Foo&& rhs) noexcept
{
m_data = rhs.m_data;
rhs.m_data = nullptr;
}
Foo& operator = (Foo&& rhs) noexcept
{
m_data = rhs.m_data;
rhs.m_data = nullptr;
return *this;
}
private:
void* m_data
}
移动构造的本质就是内存资源所有权的转移
#include <iOStream>
#include <cstdlib>
#define LOG(Args) std::cout << "==== " << Args << " ====" << std::endl
namespace My
{
class Vector
{
public:
Vector() noexcept
{
LOG("Ctor");
m_data = new int[] {0, 0, 0, };
}
~Vector()
{
LOG("Dector");
m_data = new int[] {0, 0, 0, };
}
Vector(const Vector& rhs)
{
LOG("Copy");
if (m_data == nullptr)
{
m_data = new int[3];
}
memcpy(m_data, rhs.m_data, 3 * sizeof(int));
}
Vector& operator = (const Vector& rhs)
{
LOG("Copy Operator = ");
if (m_data == nullptr)
{
m_data = new int[3];
}
memcpy(m_data, rhs.m_data, 3 * sizeof(int));
return *this;
};
Vector& operator = (Vector&& rhs) noexcept
{
LOG("Move Operator = ");
m_data = rhs.m_data;
rhs.m_data = nullptr;
return *this;
};
Vector(Vector&& rhs) noexcept
{
LOG("Move");
m_data = rhs.m_data;
rhs.m_data = nullptr;
}
void print()
{
std::cout << "X = " << m_data[0] <<
" , " << "Y = " << m_data[1] <<
" , " << "Z = " << m_data[2] << std::endl;
}
void set(int x,int y,int z)
{
m_data[0] = x;
m_data[1] = y;
m_data[2] = z;
}
private:
int* m_data;
};
}
My::Vector Get()
{
My::Vector vec;
vec.set(4, 5, 6);
return vec;
}
void main()
{
My::Vector vec1;
My::Vector vec2;
LOG("vec1");
vec1.print();
vec1.set(0, 1, 2);
LOG("vec1");
vec1.print();
vec1 = vec2;
LOG("vec1");
vec1.print();
vec1 = std::move(vec2);
LOG("vec1");
vec1.print();
My::Vector* vp1 = new My::Vector();
LOG("vp1");
vp1->print();
My::Vector* vp2 = new My::Vector(*vp1);
LOG("vp2");
vp2->print();
My::Vector* vp3 = new My::Vector(std::move(*vp1));
LOG("vp3");
vp3->print();
My::Vector* vp4 = new My::Vector(Get());
LOG("vp4");
vp4->print();
}
输出
到此这篇关于一文带你了解C++中的右值引用与移动语义 的文章就介绍到这了,更多相关C++右值引用 移动语义 内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: 一文带你了解C++中的右值引用与移动语义
本文链接: https://lsjlt.com/news/202723.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0