본문 바로가기
C++ 독학/[C++ 독학] C++ 배우기

[C++ 독학] 구조체 <C++ 의 기초> 06

by NpsCause 2022. 6. 6.

구조체

자료들의 집합!

 

구조체는 서로 연관성 있는 자료들을 묶어 데이터를 구조화(structuring) 하는 것이다. 

 

구조체는 기존에 정의되어 있던 자료형(int, double, string 등등,,,)을 이용해 새로운 구조체를 만들게 되는데 이것을 '구조체를 정의한다'라고 한다.


구조체 정의

먼저 우리가 자동차에 관한 정보를 작성해보다 정보는 자동차의 이름, 최고속도, 연비, 가격 등이 있다고 가정 한다.

 

아마 기존의 우리는 다음과 같이 코드를 작성했을 것이다.

string car1_name;
int car1_speed;
int car1_fuel_efficiency;
int car1_price;

끔찍하게도 자동차의 개수가 늘어갈수록 더 많은 n*4개의 변수를 생성하게 될 것이다. 이럴 때 사용할 수 있는 것이 구조체이다.(클래스도 사용할 수 있겠지만 다음장에서 설명하겠다.)

 

구조체를 사용하여 정의하면 다음과 같이 선언할 수 있다.

struct Car{
    string name;		// 이름
    int speed;			// 속도
    int fuel_efficiency;	// 연비
    int price;			// 가격
};

'Car'라는 이름의 구조체가 정의(Define) 되었고, 그 안에 정의되어 있는 변수(name, speed)등을 멤버 변수라고 부른다. 

 

이렇게 정의된 구조체를 사용하기 위해선 구조체를 선언해야 하는데 구조체를 선언함과 동시에 메모리를 할당받게 된다. 

Car c1;
Car c2;
Car c3;

c1, c2, c3라는 이름의 Car 구조체를 3개 선언(Declaration) 한 것이다. (일반적인 자료형의 선언과 유사한 것을 확인할 수 있다.)

 

구조체 선언된 메모리공간

 

구조체의 멤버로는 배열도 포함될 수 있고 다른 구조체함수도 포함될 수 있다.

 


구조체 초기화

구조체를 선언한 뒤 초기화시켜보겠다.

우선 우리가 선언한 구조체에 접근하기 위해서는 멤버 선택 연산자(Member selection operator)를 사용해야 한다. 

멤버 선택 연산자는 ' . '으로 나타내며 사용방법은 구조체.멤버 변수와 같은 방법으로 사용할 수 있다. 

 

바로 예시를 살펴보자.

Car c1;
c1.name = "My car";
c1.speed = 25;
c1.fuel_efficiency = 60;
c1.price = 30000000;

 

정리해보면

우리는 방금 Car 타입C1 구조체를 선언하고 멤버 선택 연산자를 통해서 맴버 변수를 초기화시켜 보았다.

 

 

또 C++11부터는 구조체를 선언과 동시에 초기화시키는 집계 초기화(Aggregate initialization) 유니폼 초기화(Uniform initialization)를 사용할 수 있다.

Car c1 = {"My car1", 25, 60, 23000000};		// 집계 초기화
Car c2 {"My car2", 20, 60, 50000000};		// 유니폼 초기화

위와 같이 선언하면 각 멤버 변수에 대치되는 값으로 초기화된다. 

 

구조체를 정의하는 과정에서 아예 변수의 값을 초기화시킬 수 있는데 이것을 비정적 멤버 초기화(Non-static member initialization)이라 한다.

struct Square{
	double width = 5.0;
	double height = 5.0;
};

하지만 이 방법을 사용하면 유니폼 초기화는 사용할 수 없다.

 


구조체의 활용

x, y 멤버를 가지고 있는 사각형 구조체를 예시로 사용하겠다.

struct Square{
    int x;
    int y;
};

 

구조체 배열

구조체도 다른 자료형과 같이 배열로 활용할 수 있다. 

Square sq[3];

sq[0].x = 10;
sq[0].y = 10;

sq[1].x = 14;
sq[1].y = 15;

sq[2].x = 20;
sq[2].y = 25;

배열은 인덱스로 접근하며 해당 인덱스의 멤버 변수에 접근하기 위해서는 ' . '을 사용하여 접근한다.

마찬가지로 유니폼 초기화를 사용할 수 있는데 이때는 중괄호를 중첩하여 사용한다. 

  Square sq[3] {{10, 20}, {30, 40}, {50, 60}};

 

구조체의 함수

구조체는 함수의 인자, 리턴 타입 등 다른 자료형과 같이 사용할 수 있다.

Square area(Square sq){
    return sq.x = 10 * sq.y = 20;
}

넓이를 구하는 함수

 

구조체를 매개변수로 전달할 때 기본적으로 얕은 복사가 일어나므로 모든 멤버 변수를 복사하게 된다. 다시 말해 공간 낭비가 심해진다.

때문에 포인터를 사용하여 레퍼런스로 전달하는 것이 더욱 효율적이다. (깊은 복사와 얕은 복사에 대한 내용은 추후 부록에 정리해 놓겠다.)

 


마치며

구조체는 기본적으로 스택에 자료를 저장한다. 때문에 속도는 빠르지만 구조체의 크기가 커질수록 메모리 효율이 크게 떨어지고 스택오버플로우(Stack overflow)의 위험이 있다. 이러한 문제를 해결하기 위해 나온 개념이 클래스인데 이 개념의 기본 요소들이 오늘 알아본 구조체이다. 

 

댓글