[C++] struct 구조체

2023. 7. 9. 16:16Algorithm/with C++

1. 구조체

 

구조체(struct)는 하나 이상의 변수를 그룹 지어서 새로운 자료형을 정의하는 것이다.

 

출처 : https://boycoding.tistory.com/183


가. struct와 class의 차이점

 

C++에서 클래스(class)와 구조체(struct)는 매우 유사한 방식으로 작동한다.

 

둘 다 데이터 필드와 메서드를 포함할 수 있으며, 이들을 하나의 단위로 묶는 방법을 제공한다.

 

C++에서는 구조체도 메서드를 포함할 수 있다.

 

또한 클래스와 구조체 모두 상속을 통해 기능을 확장하고 코드를 재사용할 수 있습니다.

 

  클래스(Class) 구조체(Struct)
기본 접근 제한자 Private Public
기본 상속 방식 Private Public
데이터와 메서드 모두 가능 모두 가능
생성자 및 소멸자 사용 가능 사용 가능
상속 가능 가능
다형성 지원 지원

기본 접근 제한자와 기본 상속 방식에 차이점이 있다.

 

이러한 차이점에도 불구하고, C++에서 클래스와 구조체는 기본적으로 같은 방식으로 작동한다.

 

대부분의 개발자들은 일반적으로 데이터를 그룹화하는 데 구조체를 사용하고, 데이터와 함께 동작(메서드)을 그룹화하는 데 클래스를 사용하는 경향이 있다.

 

출처 : https://novemberfirst.tistory.com/32


2. 예제

#include<iostream>
#include<vector>
using namespace std;

struct Car{
    int a, b;
    double c, d, e;
};

void print(Car car){
    cout << car.a << " " << car.b << " " << car.c << " " << car.d << " " << car.e << '\n'; 
}

int main(){
    Car car = {1, 1, 1, 1, 1};
    print(car);
    vector<Car> sonata;
    sonata.push_back({1, 2, 3, 4, 5}); 
    sonata.push_back({1, 2, 3, 4, 6}); 
    sonata.push_back({}); 
    sonata.push_back({1, 3}); 
    for(Car car : sonata){
        print(car);
    }
    return 0;
}
/*
1 1 1 1 1
1 2 3 4 5
1 2 3 4 6
0 0 0 0 0
1 3 0 0 0
*/
  • Car car = {1, 1, 1, 1, 1}; : 구조체 생성하는 방법 중 하나.

 


가. 생성자(constructor)

struct S{
    int x, y, z;
    //Overloading
    S(int X, int Y, int Z) : x(X), y(Y), z(Z) {}
    S(){x=-1; y=-1; z=-1;}
};

class나 struct을 생성할 때 생성자를 사용하게 되면 객체생성과 동시에 멤버 변수의 초기화를 진행할 수 있기 때문에 초기값을 지정해 줄 때 사용하면 유용하다.

 

#include<iostream>
#include<vector>
using namespace std;

struct S{
    int x, y, z;
    //Overloading
    S(int X, int Y, int Z) : x(X), y(Y), z(Z) {}
    S(){x=-1; y=-1; z=-1;}
};

int main(){
    vector<S> v;

    v.push_back(S(1,2,3));
    v.push_back(S(10,20,30));
    v.push_back(S());

    cout << "v[0] : " << v[0].x << " " << v[0].y << " " << v[0].z << endl;
  cout << "v[1] : " << v[1].x << " " << v[1].y << " " << v[1].z << endl;
  cout << "v[2] : " << v[2].x << " " << v[2].y << " " << v[2].z << endl;

    return 0;
}
/*
v[0] : 1 2 3
v[1] : 10 20 30
v[2] : -1 -1 -1
*/
  • S(), S(1,2,3) : 생성자 사용.

 


나. 연산자 오버로딩

#include<iostream>
#include<vector>
using namespace std;

struct S{
    int x, y, z;
    //Overloading
    S(int X, int Y, int Z) : x(X), y(Y), z(Z) {}
    S(){x=-1; y=-1; z=-1;}
    bool operator < (const S & a) const{
        if(x== a.x){
            if(y == a.y) return z < a.z;
            return y < a.y;
        }
        return x < a.x;
    }
};

int main(){
    vector<S> v;

    v.push_back(S(1,2,3));
    v.push_back(S(10,20,30));
    v.push_back(S());

    cout << "v[0] : " << v[0].x << " " << v[0].y << " " << v[0].z << endl;
  cout << "v[1] : " << v[1].x << " " << v[1].y << " " << v[1].z << endl;
  cout << "v[2] : " << v[2].x << " " << v[2].y << " " << v[2].z << endl;

    cout << "v[0]<v[1] : " << (v[0]<v[1]) << '\n' ;

    return 0;
}
/*
v[0] : 1 2 3
v[1] : 10 20 30
v[2] : -1 -1 -1
v[0]<v[1] : 1
*/

연산자 오버로딩은 기존의 연산자들(+, - , % , / , >= , == , += , -=, ++, -- , []…)을 오버로딩하여 자신만의 방식으로 연산자를 재정의하는 것이다.

 

struct Point{ 
    int y, x;
    Point(int y, int x) : y(y), x(x){}
    Point(){y = -1; x = -1; }
    bool operator < (const Point & a) const{
        if(x == a.x) return y < a.y;
        return x < a.x; }
};

< 연산자를 재정의 하고 있다.

  • Bool : 반환하는 자료형
  • operator < : 연산자 < 를 재정의 하겠다.
  • (const Point & a) : 매개변수
  • const{…} : 상수멤버함수로 객체(여기선 구조체)의 멤버 변수의 값을 변경할 수 없는 함수다.

 

연산자 오버로딩인 operator < 함수는 원래 const 로 만들고, 매개변수도 const 로 받는 것이 바람직합니다.

 

구조체를 값으로 받지 않고 주소로 받은 것.

 

구조체는 기본형 변수보다는 크기가 크다.

 

값으로 받으면 프로그램 속도가 느려진다.

 

속도를 높이기 위해 주소로 받는다.

 

그런데 주소로 받으면 operator < 함수가 구조체의 주소에 접근해 값을 변경할 수 있는 가능성이 있어 보안에 취약해진다.

 

const Point & a 처럼 읽기 전용으로 선언해 operator < 가 구조체의 값을 변경하지 못하도록 하는 것이다.

 

c++ 클래스에서 함수 헤더 뒷부분에 const를 붙이는 함수를 상수멤버함수라고 합니다.

 

상수멤버함수는 객체의 멤버변수(여기선 a.x, a.y)를 읽기만 하지 값을 변경할 수 없는 함수다.

 

즉 둘 다 보안을 위해 const를 붙이는 것이며, 연산자 오버로딩 함수가 const로 작성된 것일 때만 에러 없이 작동을 합니다.

 

 

C++은 할건데, C랑 다른 것만 합니다. 6편 연산자 오버로딩 1, 대입 연산자, 산술 연산자, 비교 연산

https://modoocode.com/202연산자 오버로딩은 기존에 있는 연산자들(+, - , % , / , >= , == , += , -=, ++, -- , \[] 등등)을 오버로딩하여 구현하는 것으로 해당 연산자에 자신이 원하는 로직을 구현할 수 있다.주

velog.io

 

bool operator< 질문드립니다. - 인프런 | 질문 & 답변

크루스칼에서 bool operator을 작성할떄는bool operator<( Edge &b){ return val > b.val;}와 같이 했엇는데왜 프림에서는bool operator<(const Edge &b)const { return ...

www.inflearn.com

 

 

상수 멤버 함수 (const member function)

1. 상수 멤버 함수는 멤버 변수를 변경시키지 않는 멤버 함수를 나타내는 것으로, (반환형) (함수이름)(함수인자) const { 구현 } 이런 식으로 인자와 구현 사이에 const 키워드를 넣는다. class Point { pu

mufflemumble.tistory.com

 


다. 구조체 정렬

 

#include<iostream>
#include<vector>
using namespace std;

struct Point{
    int x, y;
};
bool cmp(const Point & a, const Point & b){
    return a.y > b.y; //y값 기준 내림차순
}
vector<Point> v;
int main(){
    for(int i = 10; i >= 1; i--){
        v.push_back({i, 10-i});
    }
    sort(v.begin(), v.end(), cmp); //custom 비교 함수가 true이도록 정렬
    for(auto i : v) cout << i.x << " : " << i.y << '\n';
    return 0;
}
/*
1 : 9
2 : 8
3 : 7
4 : 6
5 : 5
6 : 4
7 : 3
8 : 2
9 : 1
10 : 0
*/

 

커스텀 비교함수를 사용해서 sort() 함수로 구조체를 쉽게 정렬할 수 있다.

 


'Algorithm > with C++' 카테고리의 다른 글

[C++] 순열  (0) 2023.07.10
[C++] call by value? reference?  (0) 2023.07.09
[C++] stack & queue & deque & priority_queue  (0) 2023.07.09
[C++] set & multiset  (0) 2023.07.09
[C++] map & unordered_map  (0) 2023.07.09