2024.12.11 (강의는 12.09). 나는 말하는 감자임이 틀림 없다.

9. operator overloading

operator (연산자)

assignment
increment
decrement
arithemetic
logical
comparison
member
access
other
a = b
a += b
a -= b
a *= b
a /=b
a %=b
a &=b
(비트AND 대입)
a |= b
(비트 OR 대입)
a ^= b
(비트 XOR 대입)
a <<= b
(비트 왼쪽
시프트 대입)
a >>= b
(비트 오른쪽
시프트 대입)
++a
--a
a++
a--
+a
(단항덧셈,
정수승급)
-a
(단항뺄셈, 반수)
a+b
a-b
a*b
a/b
a%b
~a (비트 not)
a&b (비트 and)
a | b (비트 or)
a^b (비트 xor)
a << b
(비트 좌 이동)
a >> b
(비트 우 이동)
a&&b
(and)
a | | b
(or)
!a
(not)
a == b
a != b
a < b
a > b
a <= b
a >= b
a <=> b
(삼단비교)
???
예제 ) auto T::operator<=>
(const T& b) const;
a [b]
(포인터 배열)
*a
(포인터)
&a
(참조)
a -> b
(포인터 a에 할당된 객체의 멤버b)
a.b (오버로드X)
(객체 a의 맴버b)
a -> *b
(포인터 a에 할당된 객체의 멤버 b에 할당된 멤버)
a.*b (X)
(객체 a의 b에
할당된 멤버)
a(...)
(함수호출)
a, b
(쉼표)
a?b :c (X)
(삼항연산자)
a :: b (X)
(범위확인)

xor = 두 값의 각 자리수를 비교해 값이 같으면 0, 다르면 1 계산

    • operator overloading (연산자 오버로딩)
primitive type
연산자를 default로 사용 가능
custom data type
특정한 기준이 없으므로 연산자 사용 불가
int a=3, b=4;
a != b : true
a+b = : 7
a > b : false
struct Data {int x, y;}
a == b ?
a+b = ?
a > b ?

=> 때문에 이를 정의해주는 것이 operate overloading!

    • Member function Overloading (global function overloading(외부에서 불러오는 것)은 생략)
struct Data{
     int x,y;
     bool operator==(Data r){           // bool = T/F반환하게 하는
          return x == r.x.&& y==r.y;    // x,y가 둘다 같으면 T반환
     }

     bool operator<(Data r){
          if(x != r.x) return x<r.x;    // 대소비교
          return y<r.y;
     }

     void operator()() {
          cout << x << ' ' << y;
     }

     void operator() (Data r) {
          x += r.x;
          y += r.y;
     }
};

 

이거를 적용하면 이렇게 됨

Data a,b;

// 앞에 작성한 것이 기준이 되어서 뒤에 꺼를 매개변수로 함수를 호출함. r자리
a==b  // : a.operator == b 이거랑 동일
a<b   // : a.operator<(b)
a()   // : a.operator()()
a(b)  // : a.operator()(b)

 

10. function object 함수를 인자로

: STL container에서 기준설정할 때 사용함.

set<T, Compare>
unordered_set<T, Hash, KeyEqual>

// 여기에서 Compare, Hash, KeyEqual이 function object임.
    • function point (추후 구글링해서 공부해보기)
    • function object (functor)

: function call operatoe()를 정의하여 함수처럼 사용 가능한 객체

인라인 치환 (함수 이름앞에 inline을 붙이면 일반 함수와 달리, 프로그램이 생성될때 함수가 치환되어 생성됨. 근데 요즘은 알아서 최적화해서 신경X)

상태를 가질 수 있고, 다른 함수의 인자로 전달될 수 있다.

struct Sum_n{
          int operator()(int n){
                    int sum = 0;
                    for(int i=1;i <=n; i++) sum += i;
                    return sum;
          }
}Sum_n; // 1~n까지의 합을 반환하도록 하는 함수.

// 함수를 호출하려면
cout << Sum_n(10);               // 55가 출력됨.
cout << Sum_n{}(10);             // 생성자 붙이기 => 임시객체를 만들고 이걸 통해 10을 함수에 반환해주는 것
cout << Sum_n()(10);               // 생성자 붙이기
// Sum_n.operator()(10) : 이것과 동일함.

: 함수를 호출하기 위해서는 객체가 필요함.

① 실제 객체 만들어주기 (인스턴트화)

임시객체를 생성해서 처리하기 ( ), { }

    • Predefined functor : compaision operator

: 이미 정의된 것 중 사용할 것 정리

      • set, map, priority_queue 에서 default로 less 사용
      • unordered_set, unordered_map 에서 default로 equal_to 사용
      • data type에 각각 operator==, operator<, operator>가 정의되어있어야함.
// 1. equal_to
template <class T>             // less<T> 형태는 class, container
struct equal_to{               // less<T>(), less<T>{} 형태는 function, algorithm
     bool operator()(const T&lhs, const T&rhs) const{
          return lhs == rhs;
     }                         
}    //바디 내에서 어떤 값도 바꿀 수 없도록 전부 상수화하기(필수**) 참조자는 선택, const는 필수

// 2. less
template <class T> 
struct less{
     bool operator()(const T&lhs, const T&rhs) const{
          return lhs < rhs;
     }                         
}    //바디 내에서 어떤 값도 바꿀 수 없도록 전부 상수화하기(필수**) 참조자는 선택, const는 필수

// 3. greater
template <class T> 
struct greater{
     bool operator()(const T&lhs, const T&rhs) const{
          return lhs > rhs;
     }                         
}    //바디 내에서 어떤 값도 바꿀 수 없도록 전부 상수화하기(필수**) 참조자는 선택, const는 필수

 

**Hash

struct hash{
     size_t operator()(const key &key)const{
          return (hash value);
     }
};   // : key값을 받아 그 값의 hash value를 반환

 

- Requirement

- key값에 대해 size_t type의 hash값을 반환 (size_t == unsigned long long)

- k1, k2가 같다면 hash<key>(k1) == hash<key>(k2) 이어야한다.

- k1, k2가 다르다면 hash<key>(k1) == hash<key>(k2) 인 확률이 매우 적어야한다.

- Specialization** 되어있는 type

- 기본 primitive (int, long long, char, boo, double, float...)

- string

- pair, 다른 커스텀데이터는 불가능. 직접 구현해서 만들어야함.

**Specialization : 특정 data type에 대해 별도의 동작을 정의해줌. 즉, 각 type의 특성에 맞게 hash function이 적절히 구현되어있음.

    • lambda (추후 추가적으로 구글링해서 공부해보기)

익명함수|객체함수

[captures](parameters) -> return type {body};
//captures : scope 내의 외부변수를 reference of value로 참조가능
// parameter : 매개변수 (없으면 생략 가능)
// return type : 생략시 body(함수 본문)의 return type으로 결정

 

captures 활용

[] : 외부변수 사용x

[] : 외부변수 사용x
[&] : scope 내의 모든 외부변수들을 레퍼런스로 가져옴.
[=] : scope 내의 모든 외부 변수들을 값으로 가져옴
[=, &x] : x(reference참조) / 나머지 (value 참조)
[x, &y, &z] : x(value 참조) / y, z (reference 참조)
auto Sum_n = [](int n) {
     int sum = 0;
     for(i=1; i<=n; i++) sum +=1;
};
sum_n(10); // result : 55

int arr [5] {1,2,3,4,5};
auto increase = [&]{
     for (int i = 0; i<5; i++) arr[i]++;
};
increase(); // arr : 2,3,4,5,6
 

+ Recent posts