trivial

보물창고·2023년 1월 24일
0

1. Trivial

: 사소한, 하찮은 이라는 의미를 가짐.

  • c++에서는 기본 생성자가 하는 일이 없을 때를 말함.

  • 예시 코드 1번 ( 가상함수가 있을 때)
    : 결과는 false가 출력됨.
    -> 기본생성자가 없지만, A클래스의 경우, 디폴트생성자가 func 가상함수에 대한
    가상함수 포인터를 설정하는 등의 일을 하기 때문에,
    --> 이때는 기본생성자가 일을 하고 있는 것으로 간주함.

class A
{
	public : 
    virtual void func() {}
}

int main()
{
	cout << is_trivially_constructible<A>::value << endl;
}

  • 예시 코드 2번 ( 선언부에서 기본 생성자의 정의부를 구현할 때)
    : 선언하는 부분에서 정의부를 구현할 경우,
    -> 이 때도 생성자에서 일을 하고 있는 것으로 간주함.
class A
{
	public : 
    A() {}
}


int main()
{
	cout << is_trivially_constructible<A>::value << endl;
}

2. Triavial이 왜 필요한지?

예시코드 1번.

: 모든 타입을 복사하는 함수를 만들어보자는 생각을 하면,
이러한 copy_type 함수를 만들 수 있음.


template <typename T>void copy_type(T* dst, T* src, int sz)
{
	memcpy(dst, srt, sizeof(T) * sz);
}

int main()
{
	char s1[10] = "hello";
    char s2[10] = {0};
    
    copy_type(s1, s2, 10);
}

  • 1) 만약 유저타입이 있다고 한다면, 멤버 데이터에 대한 복사 생성자가
    호출되어야 함.

  • 2) 하지만, 유저타입의 복사 생성자에서 아무일도 하지 않는다고 한다면?
    굳이 깊은 복사를 할 필요 없이 바로 예시 코드1번인 memcpy를 하는 것이 효율적임.
    -> 이때 trivial을 사용해서 확인할 수 있음!!!

  • 위 내용의 코드임.
    : 이때는 이미 메모리가 만들어졌기 때문에, placement new를 사용하면 됨!

template<typename T> void copy_type(T* dst, T* src, int sz)
{
	if(is_trivially_copyalbe<T>::value)
    {
    	cout << "copy 생성자가 trivial 할 때" << endl;
        memcpy(dst, srt, sizeof(T) * sz);
    }
    else
    {
    	while(sz--)
        {
        	new (dst) T(*srt);
            ++dst, ++src;
        }
    }
}

struct People
{
	People() {}
    People(const People &){}
}


int main()
{
	People s1[10];
    People s2[10];
    
    copy_type(s1, s2, 10);
}

예시 1번 코드를 다르게 복사하는 방법.

  • template 프로그래밍 강의를 수강해야 함.

  • 일단은 복사 생성자에 대한 정의가 없을 때는 1번째 함수를 사용하고,
    정의가 있다면 2번째 함수를 사용한다고 함.

template<typename T>
typename enable_if< is_trivially_copyable<T>:: value>
:: type copy_type (T * dst, T *src, int sz)
{
	cout << "copy 생성자가 trivial 할 때" << endl;
        memcpy(dst, srt, sizeof(T) * sz);
}

template<typename T>
typename enable_if< !is_trivially_copyable<T>:: value>
:: type copy_type (T * dst, T *src, int sz)
{
		cout << "copy constructor 가 존재할 경우 " << endl;
		while(sz--)
        {
        	new (dst) T(*srt);
            ++dst, ++src;
        }
}

3 정리 .

trivial이 true인 경우
1. 객체형 멤버가 없어야 함.
2. 상속된 기반 클래스에서 기본생성자가 정의되지 않아야 함.
3. 가상 함수 없어야 함.
4. 멤버 데이터를 선언과 동시에 초기화 하지 않아야 함.

profile
🔥🔥🔥

0개의 댓글