看一下下面这个例子
template<class T>
class Auto_ptr3
{
T* m_ptr;
public:
Auto_ptr3(T* ptr = nullptr)
:m_ptr(ptr)
{
}
~Auto_ptr3()
{
delete m_ptr;
}
// Copy constructor
// Do deep copy of a.m_ptr to m_ptr
Auto_ptr3(const Auto_ptr3& a)
{
m_ptr = new T;
*m_ptr = *a.m_ptr;
}
// Copy assignment
// Do deep copy of a.m_ptr to m_ptr
Auto_ptr3& operator=(const Auto_ptr3& a)
{
// Self-assignment detection
if (&a == this)
return *this;
// Release any resource we're holding
delete m_ptr;
// Copy the resource
m_ptr = new T;
*m_ptr = *a.m_ptr;
return *this;
}
T& operator*() const { return *m_ptr; }
T* operator->() const { return m_ptr; }
bool isNull() const { return m_ptr == nullptr; }
};
class Resource
{
public:
Resource() { std::cout << "Resource acquired\n"; }
~Resource() { std::cout << "Resource destroyed\n"; }
};
Auto_ptr3<Resource> generateResource()
{
Auto_ptr3<Resource> res(new Resource);
return res; // this return value will invoke the copy constructor
}
int main()
{
Auto_ptr3<Resource> mainres;
mainres = generateResource(); // this assignment will invoke the copy assignment
return 0;
}
输出:
Resource acquired
Resource acquired
Resource destroyed
Resource acquired
Resource destroyed
Resource destroyed
好多构造函数和析构函数执行,下面分析一下每个打印代表的步骤
1)nside generateResource() new Resource构造函数调用
2)generateResource 返回main,res调用copy构造函数给一个临时变量
- res在generateResource退出后调用析构函数
4)临时变量调用copy构造函数给mainres - 临时变量调用析构函数
- main退出,mainres 调用析构函数
优化如下:
#include <iostream>
template<class T>
class Auto_ptr4
{
T* m_ptr;
public:
Auto_ptr4(T* ptr = nullptr)
:m_ptr(ptr)
{
}
~Auto_ptr4()
{
delete m_ptr;
}
// Copy constructor
// Do deep copy of a.m_ptr to m_ptr
Auto_ptr4(const Auto_ptr4& a)
{
m_ptr = new T;
*m_ptr = *a.m_ptr;
}
// Move constructor
// Transfer ownership of a.m_ptr to m_ptr
Auto_ptr4(Auto_ptr4&& a)
: m_ptr(a.m_ptr)
{
a.m_ptr = nullptr; // we'll talk more about this line below
}
// Copy assignment
// Do deep copy of a.m_ptr to m_ptr
Auto_ptr4& operator=(const Auto_ptr4& a)
{
// Self-assignment detection
if (&a == this)
return *this;
// Release any resource we're holding
delete m_ptr;
// Copy the resource
m_ptr = new T;
*m_ptr = *a.m_ptr;
return *this;
}
// Move assignment
// Transfer ownership of a.m_ptr to m_ptr
Auto_ptr4& operator=(Auto_ptr4&& a)
{
// Self-assignment detection
if (&a == this)
return *this;
// Release any resource we're holding
delete m_ptr;
// Transfer ownership of a.m_ptr to m_ptr
m_ptr = a.m_ptr;
a.m_ptr = nullptr; // we'll talk more about this line below
return *this;
}
T& operator*() const { return *m_ptr; }
T* operator->() const { return m_ptr; }
bool isNull() const { return m_ptr == nullptr; }
};
class Resource
{
public:
Resource() { std::cout << "Resource acquired\n"; }
~Resource() { std::cout << "Resource destroyed\n"; }
};
Auto_ptr4<Resource> generateResource()
{
Auto_ptr4<Resource> res(new Resource);
return res; // this return value will invoke the move constructor
}
int main()
{
Auto_ptr4<Resource> mainres;
mainres = generateResource(); // this assignment will invoke the move assignment
return 0;
}
输出:
Resource acquired
Resource destroyed
1)第一步同上
2)函数返回,保存返回值给临时变量,调用move constructed函数,只进行指针copy
3)函数返回,res回收,由于res不指向任何值,因此没操作
4)临时变量赋值给mainres,同第2不
5)main退出,临时变量不指向任何值,无操作
6)main退出,mainres 调用析构函数"Resource destroyed"执行
那么什么条件下执行copy构造函数,什么情况下调用Move构造函数
1) 如果我们给一个l-value赋值的时候,调用copy构造函数
2)如果给一个r-value赋值的时候,调用Move构造函数,因为r-value都是临时的,将要被销毁的
在上面的例子中,generateResource()函数返回值调用的是move构造函数,而不是copy构造函数,跟第一条不符?C++定义函数返回值是调用move即使是给l-value复制。
网友评论