tangjikede 2020-06-21
std::vector<int> a;
auto b = a;
auto& c = b;
auto d = std::move(b);
a是左值,因为我们能取到a的地址;
b是左值,因为b是有地址并且有类型的。
c是b的引用,可以取到地址,因此c也是一个左值
move是一个辅助函数,他告诉编译器,想办法把函数括号中的东西转成右值。右值拥有的一切特征,左值都拥有,因此可以把左值转换成一个右值。
因此上图中d是一个右值。
原文链接:https://blog.csdn.net/vaew_a_n/article/details/106449371
1.c++11之前类实现的三个基本原则
1.析构函数(当一个对象的生命周期结束时对一些手动申请的资源进行释放)
2.拷贝构造函数(涉及浅拷贝的问题,当该类有对堆区内存进行申请时如果使用默认的拷贝构造函数时只是简单的将堆区的内存地址赋值给了一另一个使用对象,而当资源释放时就会涉及到同一内存被释放多次的问题。)
3.赋值构造函数(和浅拷贝的问题基本一致)
2. c++11标准
c++11之后因为右值引用语法的推出又多出了两个新的基本原则
1.move拷贝构造函数(当这个对象用于初始化另一个对象时,这个对象内对手动申请的内存的使用权会转交给另一个对象)
2.move赋值构造函数(当这个对象赋值给另一个对象时,这个对象内对手动申请的内存的使用权会转交给另一个对象)
3.五个基本原则的代码实现以及它们的如何被调用的
1.析构函数:当类的生命周期结束时
2.拷贝构造函数:当一个对象初始化另一个对象时
3.赋值构造函数:当一个对象赋值给另一个对象时
4.move拷贝构造函数:使用move语义将一个对象初始化另一个对象
5.move赋值构造函数:使用move语义将一个对象赋值给另一个对象
6.具体代码实现
#include <iostream>
//因为实现较为简单所有选用单文件的类内实现
class Base
{
public:
//构造函数
Base():m_iptr(new int(10))
{
std::cout << "Base()" << std::endl;
};
Base(int i) :m_iptr(new int(i))
{
std::cout << "Base(int i)" << std::endl;
}
//拷贝构造函数
Base(const Base& base)
{
//判断是否为同一块内存空间且不指向nullptr
if (&base != this && &base != nullptr)
{
this->m_iptr = new int(*(base.m_iptr));
std::cout << "Base(const Base& base)" << std::endl;
}
}
//赋值构造函数
Base& operator=(const Base& base)
{
//判断是否为同一块内存空间且不指向nullptr
if (&base != this && &base != nullptr)
{
this->m_iptr = new int(*(base.m_iptr));
std::cout << "Base& operator=(const Base& base)" << std::endl;
}
return *this;
}
//move拷贝
Base(Base&& base)
{
if (&base != this && &base != nullptr)
{
if (this->m_iptr != nullptr)
{
delete this->m_iptr;
this->m_iptr = nullptr;
}
this->m_iptr = base.m_iptr;
base.m_iptr = nullptr;
std::cout << "Base(Base&& base)" << std::endl;
}
}
//move赋值
Base& operator=(Base&& base)
{
if (&base != this && &base != nullptr)
{
if (this->m_iptr != nullptr)
{
delete this->m_iptr;
this->m_iptr = nullptr;
}
this->m_iptr = base.m_iptr;
base.m_iptr = nullptr;
std::cout << "Base& operator=(Base&& base)" << std::endl;
}
return *this;
}
//析构函数
~Base()
{
if (m_iptr != nullptr)
{
delete m_iptr;
m_iptr = nullptr;
}
std::cout << "~Base()" << std::endl;
};
private:
int* m_iptr;
};
int main()
{
//调用
{
Base b1;//调用构造函数
Base b2 = b1;//调用拷贝构造
Base b3;
b3 = b1;//调用赋值构造
//使用c++11的move语义调用类的move拷贝和赋值构造函数
Base b4 = std::move(b2);//调用move拷贝构造
b4 = std::move(b3);//调用move赋值构造函数
}
return 0;
}
补充概要:
c++11的右值引用解决了类中存在的一些问题比如临时对象等等,那什么是右值引用其实右值引用就是将左值转换为右值使用我们都知道左值拥有右值的一切行为和特征所以左值可以被当做右值使用。