15.4 std::move
AutoPtr.h
#include <iostream>
using namespace std;
template<typename T>
class AutoPtr
{
public:
T* m_ptr;
public:
AutoPtr(T* ptr = nullptr)
:m_ptr(ptr)
{
cout << "AutoPtr default constructor" << endl;
}
~AutoPtr()
{
cout << "AutoPtr destructor" << endl;
if (m_ptr != nullptr) delete m_ptr;
}
AutoPtr(const AutoPtr& a) // ๐๋ณต์ฌ ์์ฑ์๐
{
cout << "AutoPtr copy constructor" << endl;
// deep copy
m_ptr = new T;
*m_ptr = *a.m_ptr; // ๐Resource.h ์ ๋์
์ฐ์ฐ์ ํธ์ถํ์ฌ ๊น์ ๋ณต์ฌ ์ํ
}
AutoPtr& operator = (const AutoPtr& a) // ๐๋์
์ฐ์ฐ์ ์ค๋ฒ๋ก๋ฉ๐
{
cout << "AutoPtr copy assignment" << endl;
if (&a == this)
return *this;
if (m_ptr != nullptr) delete m_ptr;
// deep copy
m_ptr = new T;
*m_ptr = *a.m_ptr; // ๐Resource.h ์ ๋์
์ฐ์ฐ์ ํธ์ถํ์ฌ ๊น์ ๋ณต์ฌ ์ํ
return *this;
}
//AutoPtr(const AutoPtr& a) = delete;
//AutoPtr& operator = (**const** AutoPtr& a) = delete;
AutoPtr(AutoPtr&& a) // ๐์ด๋์์ฑ์๐
: m_ptr(a.m_ptr) // ์์ ๊ถ ์ด์
{
a.m_ptr = nullptr; // ์์ ๊ถ ๋ฐํ
cout << "AutoPtr move constructor" << endl;
}
AutoPtr& operator = (AutoPtr&& a) // ๐์ด๋ ๋์
์ฐ์ฐ์ ์ค๋ฒ๋ก๋ฉ๐
{
cout << "AutoPtr move assignment" << endl;
if (&a == this)
return *this;
if (m_ptr != nullptr) delete m_ptr;
m_ptr = a.m_ptr; // ์์ ๊ถ ์ด์
a.m_ptr = nullptr; // ์์ ๊ถ ๋ฐํ
return *this;
}
T& operator *() const { return *m_ptr; }
T& operator ->() const { return m_ptr; }
bool inNull() const { return m_ptr == nullptr; }
};
main.cpp
#include <iostream>
int main()
{
{
AutoPtr<Resource> res1(new Resource(10000000));
cout << res1.m_ptr << endl;
AutoPtr<Resource> res2 = res1; // ๋ณต์ฌ ์์ฑ์๊ฐ ํธ์ถ๋๋ค. res1์ L-Value๋๊น
//move semantics๋ก ๋ฐ๊พธ๊ณ ์ถ๋คํ๋ฉด AutoPtr<Resource> res2 = std::move(res1); //L-value๋ฅผ R-value๋ก ๋ฐ๊ฟ์ค๋ค.
cout << res1.m_ptr << endl;
cout << res2.m_ptr << endl;
}
return 0;
}
์ถ๋ ฅ
Resource length constructed
AutoPtr default constructor
0033F510
AutoPtr copy constructor
Resource default constructed
Resource copy assignment
0033F510
0033F5F0 // => ์ฃผ์๊ฐ ๋ค๋ฅด๋ค // copy semantics
AutoPtr destructor
Resource destroyed
AutoPtr destructor
Resource destroyed
์ถ๋ ฅ
Resource length constructed
AutoPtr default constructor
001FF540
AutoPtr move constructor
00000000
001FF540
AutoPtr destructor
Resource destroyed
AutoPtr destructor
๋ค๋ฅธ ์์
#include <iostream>
using namespace std;
template<class T>
void MySwap(T &a, T &b)
{
//T tmp = a;
//a = b;
//b = tmp;
T tmp{ std::move(a) };
a = std::move(b);
b = std::move(tmp);
}
int main()
{
{
AutoPtr<Resource res1(new Resource(3));
res1->setAll(3);
AutoPtr<Resource> res2(new Resource(5));
res2->setAll(5);
MySwap(res1, res2);
res1->print();
res2->print();
}
return 0;
}
Resource.h
#include <iostream>
using namespace std;
class Resource
{
public:
int * m_data = nullptr;
unsigned m_length = 0;
public:
Resource() // ๊ธฐ๋ณธ ์์ฑ์
{
cout << "Resource constructed" << endl;
}
Resource(unsigned length) // ์ผ๋ฐ ๋งค๊ฐ๋ณ์ 1๊ฐ ์์ฑ์
{
cout << "Resource length constructed" << endl;
this->m_data = new int[length];
this->m_length = length;
}
Resource(const Resource &res) // ๐๋ณต์ฌ ์์ฑ์๐
{
cout << "Resource copy constructed" << endl;
Resource(res.m_length);
for (unsigned i = 0; i < m_length; ++i) // ๋ด์ฉ๋ฌผ์ ์ ๋ถ ๊น์ ๋ณต์ฌ (์๊ฐ์ด ๊ฝค ๊ฑธ๋ฆผ)
m_data[i] = res.m_data[i];
}
~Resource() // ์๋ฉธ์
{
cout << "Resource destroyed" << endl;
}
Resource & operator = (Resource & res) // ๐๋์
์ฐ์ฐ์ ์ค๋ฒ๋ก๋ฉ๐
{
cout << "Resource copy assignment" << endl;
if (&res == this) return *this; // ๋์
ํ๋ ค๋๊ฒ ์๊ธฐ ์์ ์ด๋ฉด ์๋ฌด๊ฒ๋ ์ํจ
if (this->m_data != nullptr) delete[] m_data; // 1. ๋ด ์์ ์ m_data ๋น์์ฃผ๊ธฐ
m_length = res.m_length; // 2. ๋์
์ผ๋ก ๋๊ฒจ๋ฐ์ res์ length ๋ก ๋ด length ๊ฐฑ์
m_data = new int[m_length]; // 3. ๋น์์ง ๋ด ์์ ์ m_data์ ์๋ก์ด ๊ณต๊ฐ ํ ๋น๋ฐ๊ธฐ
for (unsigned i = 0; i < m_length; ++i) // 4. m_data๋ด์ฉ๋ฌผ ๋ฃ๊ธฐ.
m_data[i] = res.m_data[i]; // ๋์
์ผ๋ก ๋๊ฒจ๋ฐ์ res์ m_data ๋ด์ฉ๋ฌผ๋ค์ **๋ด m_data**์ ๊น์ ๋ณต์ฌ
return *this;
}
void print()
{
for(unsigned i=0;i<m_length;++i)
std::cout << m_data[i] << " ";
std::cout << "\n";
}
void setAll(const int& v)
{
for (unsigned i=0;i<m_length;++i)
{
m_data[i] = v;
}
}
};
๋ค๋ฅธ ์์
#include <iostream>
#include <utility> // โจโจ
#include <vector>
int main()
{
{
vector<string> v;
string str = "Hello";
v.push_back(str); //copy semantics
cout << str << endl; // Hello ๊ทธ๋๋ก ์๋ค.
cout << v[0] << endl;
v.push_back(std::move(str)); // move semantics
cout << str << endl;
cout << v[0] << " " << v[1] << endl;
}
return 0;
}
์ถ๋ ฅ
Hello
Hello
๐ null ์ด์ด์ ๋น์์ง ๋ถ๋ถ
Hello Hello