Notice
Recent Posts
Recent Comments
Link
- 책_곽용재님 홈페이지
- 책_노란북 - 책 가격비교
- 책_김재우-SICP번역
- 플밍_쏘쓰포지
- 플밍_CodingHorror ?
- 플밍_상킴
- 플밍_김민장님
- GPGStudy
- 플밍_미친감자님
- 플밍_jz
- 플밍_샤방샤방님
- 플밍_글쓰는프로그래머2
- 플밍_키보드후킹
- 사람_재혁
- 사람_kernel0
- 사람_박PD
- 사람_경석형
- 사람_nemo
- 사람_kikiwaka
- 사람_Junios
- 사람_harry
- 사람_어떤 개발자의 금서목록..
- 사람_모기소리
- 사람_낙타한마리
- 사람_redkuma
- 사람_영원의끝
- 사람_민식형
- 도스박스 다음카페
- 플레이웨어즈 - 게임하드웨어벤치마크
- http://puwazaza.com/
- David harvey의 Reading Marx's c…
- 씨네21
- 한겨레_임경선의 이기적인 상담실
- 본격2차대전만화 - 굽시니스트
- 영화_정성일 글모음 페이지
- 영화_영화속이데올로기파악하기
- 음식_생선회
- 죽력고
- 사람_한밀
- 플밍_수까락
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 정성일
- programming challenges
- template
- Programming
- modernc++
- 진삼국무쌍5
- 게임
- BSP
- 건강
- 프로그래밍
- 정신분석
- 고전강의
- 일리아스
- 삼국지6
- 인문학
- 노무현
- 영화
- stl
- 태그가 아깝다
- 진중권
- 책
- c++
- 단상
- 유머
- 삼국지
- 소비자고발
- 김두식
- 강유원
- 유시민
- 고등학교 사회공부
Archives
- Today
- Total
01-05 01:43
lancelot.com
trivial 본문
- Special member function
- 사용자가 제공하지 않으면 "컴파일러가 제공하는 멤버 함수"
- 디폴트 생성자 ( default constructor )
- 소멸자 ( destructor )
- 복사 생성자 ( copy constructor )
- 복사 대입연산자 ( copy assignment )
- 이동 생성자 ( move constructor )
- 이동 대입연산자 ( move assignment )
- Special member function 들이 "trivial 하다"고 하는 경우의 의미는?
- Trivial 의 조건
- 컴파일러가 생성하는 Special member function 이 다음과 같은 경우
- default constructor : 아무일도 하지 않을 때 ( no action perform )
- destructor : 아무일도 하지 않을 때 ( no action perform )
- copy constructor : 객체를 memmove( 또는 memcpy ) 로 복사하는 경우와 동일할때 ( bitwise copy )
- copy assignment : 객체를 memmove( 또는 memcpy ) 로 복사하는 경우와 동일할때 ( bitwise copy )
- move constructor : std::is_trivially_constructible<T, T&&>
- move assingment : std::is_trivially_assignable<T, TT&>
- 컴파일러가 생성하는 Special member function 이 다음과 같은 경우
- Trivial Default Constructor
- Trivially default constructor
- "컴파일러가 생성하는 디폴트 생성자" 가
- "아무일도 하지 않은 경우. ( no action perform )"
- 다음의 모든 조건을 만족해야 한다.
- The constructor is not user-provided
- T has no virtual member functions
- T has no virtual base classes
- T has no non-static members with default initializers
- Every direct base of T has a trivial default constructor
- Every non-static member of class has a trivial default constructor
- 다음의 모든 조건을 만족해야 한다.
- 조사하는 방법 - type_traits 사용
std::is_trivially_default_constructible<T>::value // C++11 std::is_trivially_default_constructible_v<T> // C++17
- Trivially default constructor
- 사용자가 제공하지 않으면 "컴파일러가 제공하는 멤버 함수"
#include<iostream>
#include<type_traits>
template<typename T>
void check()
{
std::cout << typeid(T).name() << " : ";
std::cout << std::boolalpha;
std::cout << std::is_trivially_constructible_v<T> << std::endl;
}
struct TrivialDefaultConstructor
{
int data;
};
struct NonTrivialDefaultConstructor
{
int data;
NonTrivialDefaultConstructor() {}
};
struct Type1
{
Type1(int a) {} // 인자를 받는 생성자가 있으므로, 컴파일러가 디폴트 생성자를 제공하지 않음 - false
};
struct Type2
{
Type2() {} // false
Type2(int a) {}
};
struct Type3
{
Type3() = default; // true
Type3(int a) {}
};
struct Type4 // false
{
int data=0;
// 컴파일러가 생성하는 코드 : default생성자를 만들지만, data를 초기화 함 - non trivial
// int data;
// Type() : data(0) {}
};
struct Type5
{
int data;
virtual void foo() {}// 가상함수가 있으면 default생성자에서 가상함수 테이블을 초기화함 - non trivial
};
struct Type6 // false
{
int data1;
NonTrivialDefaultConstructor data2;
// Type6() : data2() {} // NonTrivial memeber이기때문에 컴파일러가 추가한 코드 - non trivial
};
struct Type7 // true
{
int data1;
TrivialDefaultConstructor data2;
// Type7() : data2() {} // Trivial memeber이기때문에 - trivial
};
struct Type8 : public NonTrivialDefaultConstructor // false
{
int data1;
};
struct Type9 : public TrivialDefaultConstructor // true
{
int data1;
};
struct Type10 : public virtual TrivialDefaultConstructor // false
{
int data1;
// 가상상속을 하면, default 생성자에서 가상상속을 위한 초기화 구문이 필요
};
struct Type11
{
Type11() = delete; // false
};
struct Type12 // false
{
int& ref; // 참조 멤버가 있으면 default 생성자는 =delete 됨. - non-trivial
// 그래서 instance를 생성하면, 삭제된 생성자 참조로 error
};
struct Type13
{
const int c;// 상수 멤버가 있으면 생성자는 =deletel됨 - non-trivial
};
int main()
{
check<TrivialDefaultConstructor>(); // true
check<NonTrivialDefaultConstructor>(); // false
check<Type1>();
check<Type2>();
check<Type3>();
check<Type4>();
check<Type5>();
check<Type6>();
check<Type7>();
check<Type8>();
check<Type9>();
check<Type10>();
check<Type11>();
check<Type12>();
check<Type13>();
}
- trivial copy constructor
- 컴파일러가 생성한 복사 생성자가
- 사용자가 직접 객체를 "memmove"등으로 복사하는 것과 동일할 때.
"effectively copies every scalar subobject ( including, recursively, subobject of jubobjects and so forth ) of the argument and performs no other action"
#include<iostream>
#include<type_traits>
class Point
{
int x;
int y;
public:
Point() = default;
Point(int a, int b) : x(a), y(b) {}
};
int main()
{
Point pt1(1,2);
Point pt2=pt1;
Point pt3;
memmove(&pt3, &pt1, sizeof(Point));
std::cout <<std::boolalpha<< std::is_trivially_copy_constructible_v<Point> << std::endl;
}
- trivially copy constructor
- 다음의 모든 조건을 만족해야 한다.
- It is not user-provided ( that is, it is implicitly-defined or defaulted )
- T has no virtual member functions
- T has no virtual base classes
- the copy constructor selected for every direct base of T is trivial
- the copy constructor selected for every non-static class type ( or array of class type ) member of T is trivial
- 조사하는 방법 - type_traits 사용
- 다음의 모든 조건을 만족해야 한다.
std::is_trivially_copy_constructible<T>::value // C++11
std::is_trivially_copy_constructible_v<T> // C++17
- trivial copy constructor 가 필요한 경우
- T의 복사 생성자가 trivial 하다면
- 배열 전체를 memcpy 나 memmove 등으로 복사하는 것이 빠르다.
- T의 복사생성자가 trivial 하지 않다면
- 배열의 모든 요소에 대해 하나씩 "복사 생성자"를 호출해서 복사 해야 한다.
- "placement new" 또는 "std::construct_at" 사용
#include<iostream>
#include<type_traits>
struct Point
{
int x=0;
int y=0;
};
template<typename T>
void copy_type(T* dst, T* src, std::size_t sz)
{
if constexpr (std::is_trivially_copy_constructible_v<T>)
{
std::cout << "using memcpy" << std::endl;
memcpy(dst, src, sizeof(T) * sz);
}
else
{
std::cout << "using copy constructor" << std::endl;
while (sz--)
{
new(dst) T(*src);
++dst; ++src;
}
}
}
int main()
{
Point arr1[5];
// Point arr2[5];
Point* arr2 = static_cast<Point*>(operator new(sizeof(Point) * 5));
copy_type(arr1, arr2, 5);
for (int i = 0; i < 5; ++i)
arr2[i].~Point();
operator delete(arr2);
}