stl string 을 assign 할때, lazy evaluation에 관한 내용 (VC60과 70차이)
C++/STL 2008. 11. 27. 17:11stl string을 assign 을 할때, MS 제공 STL 라이브러리 버전(vc60, vc70)에 작동하는 방식이 다르다.
VC 60 stl 에서는 assign 시에 lazy evaluation을 지원하나 (조건적으로) VC70 에서는 지원하지 않는다.
int main(..)
{
string a, b;
a = "AAAAAAAAAA.. AAAA";
b = "b";
b = a; // 1)
cout << b;
b += "AAA"; // 2)
return 0;
}
위의 코드에서
VC60의 경우, b.ptr = a.ptr 와 같이 shadow copy 로 작동하나,
VC70에서는 hard copy가 이루어 진다. 즉 a string 내용이 그래도 b string으로 하드 카피가 이루어 지는 것이다.
VC60의 경우,
1) 라인에서 b.ptr = a.ptr 과 같이 shadow copy가 이루어 진고, a의 ptr에 관한 reference counter 하나 증가 시킨다 . 그러나, 2) 라인과 같이 b buf 내용이 바뀌어 버리면, 이때 hard copy가 진행되는 것이다.
VC70의 경우,
1) 라인에서 shadow copy가 아닌 hard copy가 이루어 진다.
위 내용에 따라, 아래와 코딩시에 주의를 요한다.
class MyStr
{
public:
MyStr();
MyStr(const MyStr& rhs)
{
s = rhs.s;
}
~MyStr();
private:
string s;
}
int main(int, char**)
{
CMyStr a;
a.s = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAA.. AAA";
CMyStf b(a);
// VC70에서는 hard copy가 이루어 지기 때문에, 메모리 할당 작업이 이루어 짐.
// 만일, a.s 내용이 엄청 크고, CMyStr을 stl::list의 컨테이너로 사용한다면, 경우에 따라서 VC70에서는 엄청난 메모리 할당 작업이 이루어 지기 때문에 반드시 피해야 할 내용이다.
return 0;
}
위에서 VC60 버전에서 lazy evaluation이 이루이지는 조건은 아래와 같다.
_Myt& assign(const _Myt& _X, size_type _P, size_type _M)
{
if (_X.size() < _P)
_Xran();
size_type _N = _X.size() - _P;
if (_M < _N)
_N = _M;
if (this == &_X)
erase((size_type)(_P + _N)), erase(0, _P);
else if (0 < _N && _N == _X.size() // VC60에만 있는 lazy 조건, VC70에는 없음
&& _Refcnt(_X.c_str()) < _FROZEN - 1
&& allocator == _X.allocator)
{_Tidy(true);
_Ptr = (_E *)_X.c_str();
_Len = _X.size();
_Res = _X.capacity();
++_Refcnt(_Ptr); }
else if (_Grow(_N, true))
{_Tr::copy(_Ptr, &_X.c_str()[_P], _N);
_Eos(_N); }
return (*this); }
복사할 총 길이가 > 0, 전체 문자열 복사이며, 원본의 RefCnt 가 _FROZEN -1 보다 작고, string 생성자가 같은 경우 에만 작동한다.
VC 60 stl 에서는 assign 시에 lazy evaluation을 지원하나 (조건적으로) VC70 에서는 지원하지 않는다.
int main(..)
{
string a, b;
a = "AAAAAAAAAA.. AAAA";
b = "b";
b = a; // 1)
cout << b;
b += "AAA"; // 2)
return 0;
}
위의 코드에서
VC60의 경우, b.ptr = a.ptr 와 같이 shadow copy 로 작동하나,
VC70에서는 hard copy가 이루어 진다. 즉 a string 내용이 그래도 b string으로 하드 카피가 이루어 지는 것이다.
VC60의 경우,
1) 라인에서 b.ptr = a.ptr 과 같이 shadow copy가 이루어 진고, a의 ptr에 관한 reference counter 하나 증가 시킨다 . 그러나, 2) 라인과 같이 b buf 내용이 바뀌어 버리면, 이때 hard copy가 진행되는 것이다.
VC70의 경우,
1) 라인에서 shadow copy가 아닌 hard copy가 이루어 진다.
위 내용에 따라, 아래와 코딩시에 주의를 요한다.
class MyStr
{
public:
MyStr();
MyStr(const MyStr& rhs)
{
s = rhs.s;
}
~MyStr();
private:
string s;
}
int main(int, char**)
{
CMyStr a;
a.s = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAA.. AAA";
CMyStf b(a);
// VC70에서는 hard copy가 이루어 지기 때문에, 메모리 할당 작업이 이루어 짐.
// 만일, a.s 내용이 엄청 크고, CMyStr을 stl::list의 컨테이너로 사용한다면, 경우에 따라서 VC70에서는 엄청난 메모리 할당 작업이 이루어 지기 때문에 반드시 피해야 할 내용이다.
return 0;
}
위에서 VC60 버전에서 lazy evaluation이 이루이지는 조건은 아래와 같다.
_Myt& assign(const _Myt& _X, size_type _P, size_type _M)
{
if (_X.size() < _P)
_Xran();
size_type _N = _X.size() - _P;
if (_M < _N)
_N = _M;
if (this == &_X)
erase((size_type)(_P + _N)), erase(0, _P);
else if (0 < _N && _N == _X.size() // VC60에만 있는 lazy 조건, VC70에는 없음
&& _Refcnt(_X.c_str()) < _FROZEN - 1
&& allocator == _X.allocator)
{_Tidy(true);
_Ptr = (_E *)_X.c_str();
_Len = _X.size();
_Res = _X.capacity();
++_Refcnt(_Ptr); }
else if (_Grow(_N, true))
{_Tr::copy(_Ptr, &_X.c_str()[_P], _N);
_Eos(_N); }
return (*this); }
복사할 총 길이가 > 0, 전체 문자열 복사이며, 원본의 RefCnt 가 _FROZEN -1 보다 작고, string 생성자가 같은 경우 에만 작동한다.