move semantic
TRANSCRIPT
Move Semantic
Rvalue Reference
권상구
Rvalue Reference
• Move Semantic
• Rvalue & Lvalue
• Rvalue Reference
• Copy constructor & Move constructor
Move Semantic
• 메모리의 이동방식에 대한 방법론(?!)
• 메모리를 복사하지 않고 이동함으로서 불
필요한 복사를 줄여 퍼포먼스를 향상시키
는 기법.
Move Semantic (vector)
vector<T> vec;
vec.reserve(10);
... // 10개의 요소를 담음.
vec.push_back( T() );
ve
c
Move Semantic (vector)
vector<T> vec;
vec.reserve(10);
... // 10개의 요소를 담음.
vec.push_back( T() );
ve
c
Move Semantic (vector)
vector<T> vec;
vec.reserve(10);
... // 10개의 요소를 담음.
vec.push_back( T() );
ve
cT T T T T...
m m m m m
Move Semantic (vector)
vector<T> vec;
vec.reserve(10);
... // 10개의 요소를 담음.
vec.push_back( T() );
ve
cT T T T T...
m m m m m
Move Semantic (vector)
vector<T> vec;
vec.reserve(10);
... // 10개의 요소를 담음.
vec.push_back( T() );
ve
cT T T T T...
m m m m m
T T T T T...
m m m m m
Move Semantic (vector)
vector<T> vec;
vec.reserve(10);
... // 10개의 요소를 담음.
vec.push_back( T() );
ve
cT T T T T...
m m m m m
T T T T T...
m m m m m
T
m
Move Semantic (vector)
vector<T> vec;
vec.reserve(10);
... // 10개의 요소를 담음.
vec.push_back( T() );
ve
cT T T T T...
m m m m m
T T T T T...
m m m m m
T
m
Move Semantic (vector)
vector<T> vec;
vec.reserve(10);
... // 10개의 요소를 담음.
vec.push_back( T() );
ve
c
T T T T T...
m m m m m
T
m
Move Semantic (vector)
vector<T> vec;
vec.reserve(10);
... // 10개의 요소를 담음.
vec.push_back( T() );
ve
cT T T T T...
m m m m m
Move Semantic (vector)
vector<T> vec;
vec.reserve(10);
... // 10개의 요소를 담음.
vec.push_back( T() );
ve
cT T T T T...
m m m m m
Move Semantic (vector)
vector<T> vec;
vec.reserve(10);
... // 10개의 요소를 담음.
vec.push_back( T() );
ve
cT T T T T...
m
T
m m m m m
Move Semantic (vector)
vector<T> vec;
vec.reserve(10);
... // 10개의 요소를 담음.
vec.push_back( T() );
ve
cT T T T T...
m m m m m
T T T T T...
m
T
Move Semantic (vector)
vector<T> vec;
vec.reserve(10);
... // 10개의 요소를 담음.
vec.push_back( T() );
ve
cT T T T T...
m m m m m
T T T T T...
m
T
Move Semantic (vector)
vector<T> vec;
vec.reserve(10);
... // 10개의 요소를 담음.
vec.push_back( T() );
ve
c
m m m m m
T T T T T...
m
T
Move Semantic
template<class T>
void Swap(T& a, T& b) {
T t(a);
a = b;
b = t;
}
a
b
a
b
Move Semantic
template<class T>
void Swap(T& a, T& b) {
T t(a);
a = b;
b = t;
} copy of a
a
b
t
a
b
Move Semantic
template<class T>
void Swap(T& a, T& b) {
T t(a);
a = b;
b = t;
} copy of a
copy of b
b
t
a
b
Move Semantic
template<class T>
void Swap(T& a, T& b) {
T t(a);
a = b;
b = t;
} copy of a
copy of b
copy of a
t
a
b
Move Semantic
template<class T>
void Swap(T& a, T& b) {
T t(a);
a = b;
b = t;
}
copy of b
copy of a
a
b
Move Semantic
template<class T>
void Swap(T& a, T& b) {
T t(std::move(a));
a = std::move(b);
b = std::move(t);
}
a
b
a
b
Move Semantic
template<class T>
void Swap(T& a, T& b) {
T t(std::move(a));
a = std::move(b);
b = std::move(t);
}
a
b
ta
b
Move Semantic
template<class T>
void Swap(T& a, T& b) {
T t(std::move(a));
a = std::move(b);
b = std::move(t);
}
a
b
ta
b
Move Semantic
template<class T>
void Swap(T& a, T& b) {
T t(std::move(a));
a = std::move(b);
b = std::move(t);
}
a
b
ta
b
Move Semantic
template<class T>
void Swap(T& a, T& b) {
T t(std::move(a));
a = std::move(b);
b = std::move(t);
}
a
b
a
b
너무 당연한 이야기...
저렇게 하면 당연히 빨라지겠지....
어떻게 저렇게 하냐고....
Rvalue & Lvalue
• Rvalue와 Lvalue는 다르다.
– 뭐가 다른지 아시는 분?
Rvalue & Lvalue
• Rvalue와 Lvalue는 다르다.
– Rvalue는 오른쪽에 있는거...
– Lvalue는 왼쪽에 있는거...
Rvalue & Lvalue
• Rvalue와 Lvalue는 다르다.
– Rvalue는 오른쪽에 있는거...
– Lvalue는 왼쪽에 있는거...
– 아니다.........
Rvalue & Lvalue
• Rvalue와 Lvalue는 다르다.
– Rvalue는 이름이 없는거
– Lvalue는 이름이 있는거
int a = 10;
int b = a;
vector<T> getVector();
void func( std::string );
func(“hello world”);
Rvalue & Lvalue
Rvalue Reference
• Rvalue에 이름을 주자!
int&& a = 10;
a = 20; // const 가 아니다.
int b = a;
int&& c = b; //error!!!
Rvalue Reference
• Rvalue에 이름을 주자!
void func( T& a) { cout << “Lvalue reference” << endl; }
void func( const T& a ) { cout << “const Lvalue reference” << endl; }
T t;
func( t );
func( T() );
Rvalue Reference
• Rvalue에 이름을 주자!
void func( T& a) { cout << “Lvalue reference” << endl; }
void func( const T& a ) { cout << “const Lvalue reference” << endl; }
T t;
func( t );
func( T() );
output:
Lvalue reference
const Lvalue reference
Rvalue Reference
• Rvalue에 이름을 주자!
void func( T& a) { cout << “Lvalue reference” << endl; }
void func( const T& a ) { cout << “const Lvalue reference” << endl; }
void func( T&& a ) { cout << “Rvalue reference” << endl; }
T t;
func( t );
func( T() );
Rvalue Reference
• Rvalue에 이름을 주자!
void func( T& a) { cout << “Lvalue reference” << endl; }
void func( const T& a ) { cout << “const Lvalue reference” << endl; }
void func( T&& a ) { cout << “Rvalue reference” << endl; }
T t;
func( t );
func( T() );
output:
Lvalue reference
Rvalue reference
Rvalue Reference
• 그래서 이게 뭐가 좋다는건가?
– 기존에도 const Reference 참조는 가능했지 않
나?
– 임시 변수 재사용으로 어떻게 Move Semantic
을 구현하겠다는 거지?
Rvalue Reference
• 이 값은 쓰고 버려도 될 값이다.
• 이 값은 쓰고 나면 없어진다.
• 그러니까 메모리를 다 가져와도 향후 로직
에 영향을 끼치지 않는다.
Move Constructor
class str
{
char* m_pStr;
int m_iLen;
public:
str():m_pStr(nullptr),m_iLen(0) {}
~str() { if( m_pStr ) delete[] m_pStr; }
str( const str& arg_ ) {
Set( arg_.m_pStr, arg_.m_iLen );
}
str( str&& arg_ ) {
m_pStr = arg_.m_pStr;
m_iLen = arg_.m_iLen;
arg_.m_pStr = nullptr;
arg_.m_iLen = 0;
}
str( char* arg_, int iLen ) {
Set( arg_, iLen );
}
void Set( char* arg_, int iLen ) {
if( m_pStr ) delete[] m_pStr;
m_iLen = iLen;
m_pStr = new char[m_iLen];
memcpy_s(m_pStr, m_iLen, arg_, iLen);
}
const char* Get() {
if( m_pStr )
return m_pStr;
return “null”;
}
int size() {
return m_iLen;
}
};
class str
{
char* m_pStr;
int m_iLen;
public:
str():m_pStr(nullptr),m_iLen(0) {}
~str() { if( m_pStr ) delete[] m_pStr; }
str( const str& arg_ ) {
Set( arg_.m_pStr, arg_.m_iLen );
}
str( str&& arg_ ) {
m_pStr = arg_.m_pStr;
m_iLen = arg_.m_iLen;
Move Constructor
arg_.m_pStr = nullptr;
arg_.m_iLen = 0;
}
str( char* arg_, int iLen ) {
Set( arg_, iLen );
}
void Set( char* arg_, int iLen ) {
if( m_pStr ) delete[] m_pStr;
m_iLen = iLen;
m_pStr = new char[m_iLen];
memcpy_s(m_pStr, m_iLen, arg_, iLen);
}
const char* Get() {
if( m_pStr )
return m_pStr;
return “null”;
}
str():m_pStr(nullptr),m_iLen(0) {}
~str() { if( m_pStr ) delete[] m_pStr; }
str( const str& arg_ ) {
Set( arg_.m_pStr, arg_.m_iLen );
}
str( str&& arg_ ) {
m_pStr = arg_.m_pStr;
m_iLen = arg_.m_iLen;
arg_.m_pStr = nullptr;
arg_.m_iLen = 0;
}
str( char* arg_, int iLen ) {
Set( arg_, iLen );
}
void Set( char* arg_, int iLen ) {
if( m_pStr ) delete[] m_pStr;
str():m_pStr(nullptr),m_iLen(0) {}
~str() { if( m_pStr ) delete[] m_pStr; }
str( const str& arg_ ) {
Set( arg_.m_pStr, arg_.m_iLen );
}
str( str&& arg_ ) {
m_pStr = arg_.m_pStr;
m_iLen = arg_.m_iLen;
arg_.m_pStr = nullptr;
arg_.m_iLen = 0;
}
str( char* arg_, int iLen ) {
Set( arg_, iLen );
}
void Set( char* arg_, int iLen ) {
if( m_pStr ) delete[] m_pStr;
Move Constructor
str a( str(“hello”, 5) );
str&& b = str(“hello2”, 6);
str c ( b );
str d ( std::move(a) );
cout << “a = “ << a.Get() << endl;
cout << “b = “ << b.Get() << endl;
cout << “c = “ << c.Get() << endl;
cout << “d = “ << d.Get() << endl;
Move Constructor
str a( str(“hello”, 5) ); //Move Constructor
str&& b = str(“hello2”, 6);
str c ( b ); //Copy Constructor
str d ( std::move(a) ); //Move Constructor
cout << “a = “ << a.Get() << endl;
cout << “b = “ << b.Get() << endl;
cout << “c = “ << c.Get() << endl;
cout << “d = “ << d.Get() << endl;
Move Constructor