본문 바로가기
프로그래밍/c++

std::string Ogre::String 생성자의 함수호출 낭비

by 긱플레이어 2011. 2. 1.
Ogre::String 에 대한 정보

Ogre 의 옵션에 커스텀 메모리 생성 옵션이 1인 경우에대해.....
아래의 디파인이 들어있다.
#define OGRE_STRING_USE_CUSTOM_MEMORY_ALLOCATOR 1
#if OGRE_STRING_USE_CUSTOM_MEMORY_ALLOCATOR
	typedef std::basic_string,
		STLAllocator > _StringBase;
	//생략
#else
	typedef std::wstring _StringBase;
	//생략
#endif
typedef _StringBase String;


cpp 코드 스타일로 보여주는 기능에 버그가 있어서 <> 사이의 코드가 자동으로 변경되므로
위의 코드에 이상한 부분은 직접 헤더를 열어보시길...

이렇게 선언이 되어있고..
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\xstring 파일에 들어있는
xstring 클래스 템플릿을 사용하여 메모리 alloc 만
OgreMain\include\OgreMemorySTLAllocator.h
경로에 들어있는 class STLAllocator : public STLAllocatorBase<T> 클래스로 할당을 한다.
Ogre::String 내부 로직은 std::string과 같고 메모리만 다르므로 둘은 같은 클래스라고 생각해도 큰 상관없겟다...


아래의 코드는 std::string의 내용이다..
디버그 모드에서는  _Has_debug_it 스트럭쳐를 자동생성해서 iterator의 유효성을 검사해주는 디버그 코드가 돌게된다.
_HAS_ITERATOR_DEBUGGING << 이거로 검색하면 많은 내용이 나오니 참조하시길..
아무튼 iterator 유효성 검사를 위해 속도가 많이 느려지게 된다..
직접 끌수도 있지만 자신의 코드가 완벽하다고 생각하는 사람만 끄도록 하자.
아무튼 _Tidy(); 함수를 사용해 기본 데이터를 초기화를 해준다.

아래의 코드는 release와 debug의 기본생성자를 보여준다
#if !defined(_DEBUG) || !defined(_DLL_CPPLIB) || defined(_DEFINE_EMPTY_STRING_CONSTRUCTOR)
	__CLR_OR_THIS_CALL basic_string()
		: _Mybase()
		{	// construct empty string
		_Tidy();
		}
 #else /* defined(_DEBUG) && defined(_DLL_CPPLIB) */

	#if _HAS_ITERATOR_DEBUGGING

	__CLR_OR_THIS_CALL basic_string(_Has_debug_it _Hdi = _Has_debug_it(true))
		: _Mybase()
		{	// construct empty string
		if (!_Hdi._Value)
			{
			this->_Myfirstiter = _IGNORE_MYITERLIST;
			}
		_Tidy();
		}

	#else

	__CLR_OR_THIS_CALL basic_string(_Has_debug_it _Hdi = _Has_debug_it(false))
		: _Mybase()
		{	// construct empty string
		if (!_Hdi._Value)
			{
			this->_Myfirstiter = _IGNORE_MYITERLIST;
			}
		_Tidy();
		}

	#endif
	
 #endif /* !defined(_DEBUG) || !defined(_DLL_CPPLIB) */
아래에서 Ogre::String의 생성자 함수 콜 순서를 살펴보자 
딸랑 2개의 함수만 호출..
	__CLR_OR_THIS_CALL basic_string()
		: _Mybase()
		{	// construct empty string
		_Tidy();
		}
	
	----------------------------------------------------------------------
 	void __CLR_OR_THIS_CALL _Tidy(bool _Built = false,
		size_type _Newsize = 0)
		{	// initialize buffer, deallocating any storage
		if (!_Built)
			;
		else if (_BUF_SIZE <= _Myres)
			{	// copy any leftovers to small buffer and deallocate
			_Elem *_Ptr = _Bx._Ptr;
			if (0 < _Newsize)
				_Traits_helper::copy_s<_Traits>(_Bx._Buf, _BUF_SIZE, _Ptr, _Newsize);
			_Mybase::_Alval.deallocate(_Ptr, _Myres + 1);
			}
		_Myres = _BUF_SIZE - 1;
		_Eos(_Newsize);
		}


Ogre::String temp2 = "";
위와 같은 방식의 초기화 과정
인자로 const _Elem *_Ptr <<<< 이게 들어간다.
그리고 assign 함수로 내부 값을 변경하게된다.
아래의 함수들이 모두 불러지게 된다.

마지막함수의 
if (_Inside(_Ptr))
if (_Grow(_Count))
두 if 구문 안으로 들어가진 않지만 쓸데없는 작업을 많이 하게된다.

__CLR_OR_THIS_CALL basic_string(const _Elem *_Ptr)
	: _Mybase()
	{	// construct from [_Ptr, )
	_Tidy();
	assign(_Ptr);
	}
	

----------------------------------------------------------------------
	void __CLR_OR_THIS_CALL _Tidy(bool _Built = false,
	size_type _Newsize = 0)
	{	// initialize buffer, deallocating any storage
	if (!_Built)
		;
	else if (_BUF_SIZE <= _Myres)
		{	// copy any leftovers to small buffer and deallocate
		_Elem *_Ptr = _Bx._Ptr;
		if (0 < _Newsize)
			_Traits_helper::copy_s<_Traits>(_Bx._Buf, _BUF_SIZE, _Ptr, _Newsize);
		_Mybase::_Alval.deallocate(_Ptr, _Myres + 1);
		}
	_Myres = _BUF_SIZE - 1;
	_Eos(_Newsize);
	}

----------------------------------------------------------------------
_Myt& __CLR_OR_THIS_CALL assign(const _Elem *_Ptr)
	{	// assign [_Ptr, )
	_DEBUG_POINTER(_Ptr);
	return (assign(_Ptr, _Traits::length(_Ptr)));
	}
	

----------------------------------------------------------------------
static size_t __CLRCALL_OR_CDECL length(_In_z_ const _Elem *_First)
	{	// find length of null-terminated string
//		_DEBUG_POINTER(_First);
	return (::strlen(_First));
	}
	

----------------------------------------------------------------------
_Myt& __CLR_OR_THIS_CALL assign(const _Elem *_Ptr, size_type _Count)
	{	// assign [_Ptr, _Ptr + _Count)

#if _HAS_ITERATOR_DEBUGGING
	if (_Count != 0)
		_DEBUG_POINTER(_Ptr);
#endif /* _HAS_ITERATOR_DEBUGGING */

	if (_Inside(_Ptr))
		return (assign(*this, _Ptr - _Myptr(), _Count));	// substring

	if (_Grow(_Count))
		{	// make room and assign new stuff
		_Traits_helper::copy_s<_Traits>(_Myptr(), _Myres, _Ptr, _Count);
		_Eos(_Count);
		}
	return (*this);
	}
	

결론은 !!

Ogre::String temp2 = ""; 이와 같은 초기화를 하기보단.

그냥 이렇게 Ogre::String temp1; 아무것도 안하는게 좋다는것!!!
문자열의 결과는 같다!!! -_-); 버퍼 사이즈도 같다.
하지만 쓸데없이 함수를 한번 더 부른다!!

댓글