Collection클래스는 여러 유용한 알고리즘을 구현한 메소드들을 제공한다.

1. 정렬(Sorting)

2. 섞기(Shuffling)

3. 탐색(Searching)


|정렬

Collection 클래스의 정렬은 속도가 비교적 빠르고 안정성이 보장되는 합병 정렬을 이용한다.

Collection 클래스의 sort( ) 메소드는 List 인터페이스를 구현하는 컬렉션에 대하여 정렬을 수행한다.

ex)

List<String> list = new LinkedList<String>( );

list.add("김철수");

list.add("김영희");

Collections.sort(list);


<정렬 예제1>

 

출력결과

->정렬 알고리즘을 실행하기 위하여 asList( ) 메소드를 이용하여 배열을 리스트로 변환

->sort( )를 호출하여 정렬한다.


<정렬 예제2>

 

출력결과


|섞기

정렬의 반대 동작을 한다. 즉 원소들의 순서를 랜덤하게 만든다. 게임을 구현할 때 유용하다.(카드 게임에서 카드를 랜덤하게 섞을 때 사용

<섞기 예제>

 

출력결과



|탐색

리스트 안에서 원하는 원소를 찾는 것.

<탐색 예제>

 

출력결과



'Programming Language > Java' 카테고리의 다른 글

6. 입출력-바이트스트림  (0) 2016.06.08
5. 스레드  (0) 2016.06.08
4. 예외처리  (0) 2016.06.08
2. 컬렉션  (0) 2016.06.07
1. 제네릭  (0) 2016.06.07

컬렉션이란?

자바에서 자료 구조를 구현한 클래스들을 칭하는 용어.( 리스트, 스택, 큐, 집합, 해쉬 테이블)


|컬렉션의 종류

자바는 컬렉션 인터페이스와 컬렉션 클래스로 나누어서 제공.


인터페이스

1. Collection : 모든 자료 구조의 부모 인터페이스로서 객체의 모임을 나타낸다.

2. Set : 집합을 나타내는 자료 구조

3. List : 순서가 있는 자료 구조로 중복된 원소를 가질 수 있다.

4. Map : 키와 값들이 연관되어 있는 사전과 같은 자료 구조

5. Queue : 극장에서의 대기줄과 같이 들어온 순서대로 나가는 자료구조


ArrayList

|List 인터페이스

리스트는 순서를 가지는 원소들의 모임으로 중복된 원소를 가질 수 있다.

ArrayList, Vector : List를 배열로 구현한 것

LinkedList : List를 연결 리스트로 구현한 것


|ArrayList

사용 이유 : 배열의 문제점은 배열을 생성할 때 배열의 크기가 고정된다는 점, 반면 ArrayList는 자동적으로 크기가 변경.


#기본생성    ex) ArrayList<String> list = new ArrayList<String>( );

#데이터 저장    ex) list.add("milk");

#인데스 위치에 저장    ex) list.add( 1, "APPLE");

#특정한 위치에 있는 원소 바꿈    ex) list.set( 2, "GRAPE");

#데이터를  삭제     ex) list.remove( 3 );

#인덱스 위치의 값 가져옴    ex) String s = list.get( 1 );

#현재 저장된 원소의 개수    ex) list.size( );

#특정한 데이터가 저장된 위치    ex) int index = list.indexOf("APPLE");


|반복자 사용하기

#hasNext( ) : 아직 방문하지 않은 원소가 있으면 true를 반환

#next( ) : 다음 원소를 반환

#remove( ) : 최근에 반환된 원소를 삭제


반복자를 사용하기 위해서는 먼저 ArrayList의 iterator( ) 메소드를 호출하여서 반복자 객체를 얻는다.

ex)    Iterator e = list.iterator( );


LinkedList

사용 이유 : ArrayList의 경우 중간에서 데이터의 삽입이나 삭제가 발생하는 경우 원소를 이동시켜야 한다. 따러서 연결 리스트로 구현된LinkedList가 사용됨

메소드는 ArrayList와 동일 


|배열을 리스트로 변경하기

List<String> list = Arrays.asList(new String[size]);



SET

 집합은 순서가 없고 중복을 허용하지 않음.

 가장 잘 알려진 방법이 해쉬 테이블

 해쉬 테이블 : 각각의 원소에 대하여 해쉬 코드란 정수를 계산한다. 만약 클래스 작성자라면 반드시 hashCode( )도 구현해야됨

HashSet : 해쉬 테이블에 원소를 저장

TreeSet : 레드 - 블랙 트리에 원소를 저장

LinkedHashSet : 해쉬 테이블과 연결 리스트를 결합


<HashSet 예제>

 

출력결과 


<집합을 이용한 중복된 단어 검출>

 

출력결과


|대량 연산 메소드

s1.containsAll(s2) :  만약 s2가 s1의 부분 집합이면 참

s1.addAll(s2) : s1을 s1과 s2의 합집합

s1.retainAll(s2) : s1을 s1과 s2의 교집합

s1.removeAll(s2) : s1을 s1과 s2의 차집합


집합 연산을 할 때 중요한 점은 원집합이 파괴되면 안되다는 것이다. 따라서 집합 연산을 수행하기 전에 복사본을 만들어야 한다.

<집합 연산을 이용한 예제>

 

출력결과


Queue

: 후단에서 원소를 추가하고 전단에서 원소를 삭제한다. Queue 인터페이스는 LinkedList 클래스와 PriorityQueue 클래스로 구현

: 디큐(deque)는 전단과 후단에서 모두 원소를 추가하거나 삭제할 수 있다. deque 인터페이스는 ArrayDeque와 LinkedList 클래스들로 구현


|Queue 인터페이스

public interface Queue<E> extends Collection<E>{

E element( ); // 처음에 있는 원소 가져옴(삭제하지않음) 

boolean offer(E e);

E peek( ); // 처음에 있는 원소 가져옴(삭제하지않음)

E poll( ); // 처음에 있는 원소 가져옴(삭제)

E remove( );  //처음에 있는 원소 가져옴(삭제)

}


<큐에 저장된 정수값을 1초간격으로 출력>

 

->LinkedList클래스로 큐를 생성하고 0~10까지 큐에 저장한다.

->큐가 비었는지 확인하고 비어있지 않다면 뒤에서 부터 하나씩 삭제해서 출력한다.


|우선순위큐

: 원소들이 무작위로 삽입되었더라도 정렬된 상태로 원소들을 추출, 즉 remove()를 호출할 때마다 가장 작은 원소가 추출된다.(ex, 작업스케줄링)

: 히프라고 하는 자료 구조를 내부적으로 사용


<우선순위 큐 예제>

 

출력결과

->PriorityQueue클래스로 큐객체를 생성한후 30, 80, 20을 추가

->우선순위 큐의 원소를 출력

->큐가비어있을때까지 우선순위 큐의 원소를 삭제하면서 출력 이때 가장 작은 원소 순으로 출력


Map

: 많은 데이터 중에서 원하는 데이터를 빠르게 찾을 수 있는 자료구조. 사전관 같은 자료구조이다. 즉 사전처럼 단어가 있고(키) 단어에 대한 설명(값)이있다. Map은 중복된 키를 가질 수 없다. 각 키는 오직 하나의 값에만 매핑될 수 있다.

:HashMap, TreeMap, LinkedHashMap 3가지의 클래스가 제공. 만약 키들을 정렬된 순서로 방문할 필요가 없다면 HashMap.

ex)

Map<String, Student> freshman = new HashMap<String, Student>( ); //생성

Student kim = new Student("구준표");

freshman.put("20090001", kim); // 저장


String s = "20090001";

st = freshman.get(s); // 구준표 반환


<맵을 이용한 학생자료 예제>

 

출력결과

 

->HashMap클래스를 이용해 st라는 맵객체를 만들었다 ( 키 - 문자열, 값 - Student)

->"201113511"라는 키를 가진 정보를 삭제하고 새로 삽입하였다.

->Map에 저장된 데이터를 방문하기 위해 Map.Entry라는 인터페이스를 사용하였고 모든 값을 출력하였다.


<Map 기본적인 연산 예제>

출력결과

 


-> HashMap클래스를 이용해서 Map객체 m생성

-> sample배열에 있는 값을 가져와 m객체의 빈도를 가져온다 빈도가 null이면 1 아니면 1증가시킨다.

-> MAP m의 값 출력


'Programming Language > Java' 카테고리의 다른 글

6. 입출력-바이트스트림  (0) 2016.06.08
5. 스레드  (0) 2016.06.08
4. 예외처리  (0) 2016.06.08
3. Collections클래스  (0) 2016.06.08
1. 제네릭  (0) 2016.06.07

제네릭 프로그래밍(generic programming)이란 ? 

일반적인 코드를 작성하고 이 코드를 다양한 타입의 객체에 대하여 재사용하는 객체 지향 기법.


제네릭 클래스에서는 타입을 변수로 표시한다. 이것을 타입 매개변수라고 하는데 타입 매개 변수는 객체 생성 시에 프로그래머에 의해 결정된다.

ex)

class Store<T>{

private T data;

public void set(T data)

{
    this.data = data;

}

public T get()

{
    return data;

}

}


-> Store<String> store = new Store<String>( ); //문자열을 저장하는 Store객체

-> Store<Integer> store = new Store<Integer>( ); //정수를 저장하는 Store객체


타입 매개 변수의 표기

E - Element

K - Key

N - Number

T - Type

V - Value

'Programming Language > Java' 카테고리의 다른 글

6. 입출력-바이트스트림  (0) 2016.06.08
5. 스레드  (0) 2016.06.08
4. 예외처리  (0) 2016.06.08
3. Collections클래스  (0) 2016.06.08
2. 컬렉션  (0) 2016.06.07

안녕하세요 CODER_JH입니다.

제가 가장 좋아하는 알고리즘 파트네요 ㅎㅎ


알고리즘이 뭘까요?? 위키백과의 말을 빌리도록 하겠습니다.

알고리즘어떠한 문제를 해결하기 위한 여러 동작들의 모임이다. 유한성을 가지며, 언젠가는 끝나야 하는 속성을 가지고 있다.

이렇다고 하네요..


그렇다면 본격적으로 잘 알려진 알고리즘을 하나씩 알아보도록 하겠습니다. 

먼저 가장 기본적인 탐색 알고리즘의 순차탐색과 이진탐색에 대해 알아보겠습니다.


<순차탐색>

순차탐색이란 말그대로 앞에서 부터 순차적으로 하나하나 탐색해 나가는 것입니다.

찾고자 하는 값이 앞쪽에 있다면 짧은 시간에 찾아낼 수 있지만 뒤쪽에 있다면 오래 걸리겠죠?(비효율적이란 얘기입니다.)

그림으로 알아 보도록 하겠습니다.

참쉽죠? ㅎ

코드로 작성해 보겠습니다.

-> 매우 간단하내요 arr[0] ~ arr[9] 까지 for문을 돌려 만약 찾고자하는 값가 같으면 탐색을 멈추는 소스 입니다.

-> 순차탐색의 시간복잡도는 탐색리스트가 n개라면 O(n)이 되겠내요.


다음은 이진탐색에 대해 알아보도록 하겠습니다.


<이진탐색>

이진탐색이란 이름에서 뭔가 느껴지지 않나요? 탐색할 때 마다 탐색 범위가 반으로 줄어들기 때문입니다.

이진탐색을 하기위해선 탐색 리스트가 정렬되어 있다는 전제가 있어야 합니다.

10억개의 데이터 리스트를 순차탐색으로 탐색할 때 평군 5억번의 비교를 해야됩니다. 그러나 이진탐색으로 탐색할 경우 최대 33번의 비교로 값을 찾아낼수있습니다. 이 수치만 보더라도 이진탐색이 매우 효율적이라는 것을 알수있습니다.

그림으로 알아 보도록 하겠습니다.

-> 정렬된 데이터셋에서 중간값을 구합니다. 후에 찾고자 하는 값과 비교합니다. 찾고자 하는 값이 더 크므로 5보다 작은 값은 버리고 6~10을 보게됩니다.

->6~10사이의 중간값인 8과 찾고자 하는 값을 비교합니다. 찾고자하는 값보다 크므로 8이하는 버리고 9~10을 보게됩니다.

->이렇게 9와10이남아버리면 값을찾게 됩니다.

->3번의 탐색만에 값을 찾게됬내요~

코드로 작성해 보겠습니다.

->소스도 그렇게 어려운 부분은 없는 것같내요 ㅎㅎ

->이해안가는 부분있으면 댓글 달아주세요~


탐색의 2가지 알고리즘에 대해 알아봤습니다. 기본적인 것이므로 충분히 이해하고 가시기 바랍니다.

다음 시간에는 정렬 알고리즘에 대해 하니씩 파헤쳐 보도록 하겠습니다.


 





저번 시간에 이어 vector 컨테이너에 대해 알아 보도록 하겠습니다.


vector 컨테이너는 배열 기반 컨테이너 이므로 일반 배열처럼 임의 위치의 원소를 참조하는 두 인터페이스를 제공합니다.

바로 [ ] 연산자, at( ) 멤버함수입니다.

두 인터페이스의 기능은 같지만 [ ] 연사자는 범위 점검을 하지 않아 속도가 빠르며 at( ) 멤버 함수는 범위를 점검하므로 속도는 느리자만 안전합니다.

예제를 통해 이해해 보도록 하겠습니다.


<vector의 [ ]연산자와 at( ) 멤버 함수>

->[ ] 연산자는 범위 점검 없이 동작하며 at( ) 멤버 함수는 범위 점검을 하며 동작합니다. 만약 at( ) 멤버 함수 사용시 범위를 넘어가게 되면 범위 오류인 out_of_range 가 발생하게 됩니다.


이번엔 반복자에 대해 알아 보도록 하겠습니다.

컨테이너는 모든 원소의 시작과 끝을 가리키는 반복자 begin( )과 end( ) 멤버 함수로 제공합니다.

< vector의 begin( )과 end( )>

@

->iter는 반복자이며 ++연산자로 다음 원소로 이동하고 *연산자로 가리키는 원소를 참조합니다.

그림으로 보니 이해하기 더 쉽죠?ㅎㅎ

배열 기반 컨테이너인 vector와 deque는 임의 접근 반복자를 제공하며 임의 접근 반복자는 +, -, +=, -=, [ ]연산이 가능합니다.


<insert( ) 멤버 함수의 사용>

-> 반복자가 가리키는 바로앞에 값이 삽입되내요^^


삽입을 했다면 삭제도 있어야 겟죠?

<erase( ) 멤버 함수의 사용>

->v.erase(iter) : iter가 가리키는 위치의 원소(30)을 제거. 제거된 원소의 다음 원소를 가리키는 반복자를 반환

->v.erase(v.begin( )+1, v.end( )) : 구간 [v.begin( )+1, v.end( ))의 원소 (20,40,50)을 제거


vector 컨테이너의 몇가지 멤버함수를 알아 봤는데요. 이 외에도 더많은 함수를 제공한답니다.

오늘로서 표준 시퀀스 컨테이너이자 배열기반의 컨테이너인 vector의 포스팅을 마치고 다음시간에 deque에 대해 알아 보도록 하겠습니다.

글이 딱딱한 느낌인데 재밋게 써보도록 해보겠습니다^^


'Programming Language > C++' 카테고리의 다른 글

7. vector 컨테이너(1)  (0) 2016.06.03
6. 템플릿  (0) 2016.06.01
5.함수 객체  (0) 2016.06.01
4. 함수 포인터  (1) 2016.06.01
3. STL에 필요한 주요 연산자 오버로딩(2)  (4) 2016.06.01

이번 장에서는 STL 컨테이너 중 시퀀스 컨테이너에 대하 알아보도록 하겠습니다.

STL 컨테이너는 시퀀스 컨테이너와 연관 컨테이너로 나눌 수 있습니다.

시퀀스 컨테이너 : 저장 원소가 삽입 순서에 따라 상대적인 위치를 갖는 컨테이너 (vector, list, deque)

연관 컨테이너 : 특정 정렬 규칙에 따라 상대적인 위치를 갖는 컨테이너(set, map, multiset, multimap)


먼저 시퀀스 컨테이너 중 하나인 vector컨테니어 에 대해 알아 보도록 하겠습니다.

vector 컨테이너는 배열과 비슷하여 사용이 쉽고 자주 사용되므로 잘 익혀 두시기 바랍니다.

<vector의 구조>

vector는 원소의 저장 위치가 정해지며 배열 기반 컨테이너이므로 원소가 하나의 메모리 블록에 할당된다.

시퀀스 컨테이너는 차례차례 원소를 추가하고 제거하는 push_back( )과 pop_back( )을 가지며, 첫 원소와 마지막 원소를 참조하는 front()와 back()을 가집니다. 또한 지정한 위치에 원소를 삽입할 수 있는 insert()를 가집니다. 반면 다른 시퀀스와 다르게 앞쪽에는 원소를 추가/제거할 수 없으며 뒤쪽에만 추가/제거할 수 있습니다.(다른 시퀀스 컨테이너는 앞쪽에도 추가/제거할 수 있습니다.)


그럼 예제를 통해 이해해 보도록 하겠습니다.

<vector의 push_back( )>

-> v라는 vector컨테이너를 만들고 끝부분에 10, 20, 30, 40, 50을 추가하고 출력해주는 예제입니다. 쉽죠? ㅎ

<vector의 size(), capacity(), max_size()

-> size() : 저장 원소의 개수

-> capacity() : 실제 할당된 메모리 공간

-> max_size() : 컨테이너에 담을 수 있는 최대 원소의 개수

그렇다면 결과는 어떻게 될까요??

 size()와 max_size()는 모든 컨테이너가 가지는 멤버 함수입니다. 하지만, capacity()는 유일하게 vector만이 가지는 멤버 함수입니다.

vector 컨테이너는 배열 기반 컨테이너이므로 연속한 메모리를 한 번에 할당하지만, 계속 원소가 추가될 수 있습니다. 원소가 추가될 때마다 메모리를 재할당하고 이전 원소를 모두 복사해야 한다면 너무나 비효율적일 것입니다. 따라서 재할당에 드는 성능 문제를 보완하고자 만들어지 개념이 capacity입니다. capacity()를 예제를 통해 좀 더 쉽게 이해해 보도록 하겠습니다.

<vector의 capacity()>

->결과를 보면 미리 저장할 메모리의 크기를 크게 하면 원소가 추가돼도 메모리의 크기가 변하지 않게 됩니다.

->또한 미리 메모리를 예약할 수 있는 reserve()를 제공합니다. ex) v.reserve(8) // 8만큰의 메모리 할당

<vector 생성자의 초기값 지정>

1. vector<int> v(5)  : 기본값 0으로 초기화된 size가 5인 컨테이너

2. vector<int> v(5,1) : 기본값 1로 초기화된 size가 5인 컨테이너

3. vector<int> v(v1) : v는 v2컨테이너의 복사본 컨테이너


<vector의 clear( )와 empty( )>

->v.clear() : v를 비운다.

->v.empty() : v가 비었는지 검사한다.

@

->결과를 보시면 size는 0이 되어도 메모리는 제거되지 않고 남아 있게 됩니다.

->swap방법을 이용하여 capacity를 0으로 만들수 있습니다.


<swap을 이용한 할당 메모리 제거>

@

-> 이렇게 swap을 이용하니 할당 메모리를 제거할 수 있내요~


vector 컨테이너의 남은 내용은 다음시간에 이어서 하도록 하겠습니다. ^^




<작성자 - CODER_CJH>

<참고자료 - 뇌를 자극하는 C++STL>





'Programming Language > C++' 카테고리의 다른 글

8. vector 컨테이너(2)  (0) 2016.06.03
6. 템플릿  (0) 2016.06.01
5.함수 객체  (0) 2016.06.01
4. 함수 포인터  (1) 2016.06.01
3. STL에 필요한 주요 연산자 오버로딩(2)  (4) 2016.06.01

템플릿은 STL 제너릭 프로그래밍의 핵심이라고 할 수 있습니다.

템플릿은 컴파일 타임에 클라이언트가 여러 타입의 함수나 클래스를 쉽게 생성하게 하고, 서버 코드 작성자는 좀더 일반적인 프로그램 코드를 만들고 클라이언트가 구체적인 코드를 작성함으로써 제너릭한 프로그래밍이 가능하게 합니다.

템플릿에는 함수 템플릿과 클래스 템플릿이 있습니다.

템플릿의 강력한 기능을 설명하기 위해 간단한 예제를 살펴보겠습니다.

위 예제는 간단하게 정수를 출력하는 예제입니다. 만약 여기에 실수와 문자열을 출력하는 두 함수를 추가 하려고 한다면 함수 오버로딩을 이용하면 됩니다. 그러나 함수 오버로딩은 클라이언트가 매개변수 타입을 미리 알고 있다는 전제로 만들어집니다. 만일 클라이언트에서 사용자 정의 타입을 결정해야 한다면 함수 오버로딩으로 해결할 수  없습니다. 그러나 템플릿을 이용하면 이 문제를 간단하게 해결할 수 있습니다.


위의 정수 출력 예제를 템플릿을 사용하여 사음과 같이 변형할 수 있습니다.

매우 유용한 기능이내요 ㅎ


연습 예제로 swap() 함수를 템프릿 버전으로 만들어 보겠습니다.


다음은 클래스 템플릿에 대해 알아보도록 하겠습니다.

클래스 템플릿은 함수 템플릿과 별반 다르지 않습니다. 단지 함수에서 클래스로 바뀐 것뿐입니다.

예제를 통해 알아보도록 하겠습니다.

아래 소스는 장수 자료를 저장,관리하는 Array 클래스입니다.

이렇게 정의하게 되면 여러가지 타입의 Array클래스의 객체를 사용할수 있게 됩니다.


후~ 드디어 STL에 들어가기전 기본 문법에 대해서 알아보았내요. 

다음시간에는 STL에 대해서 알아 보도록 하겠습니다.

연산자오버로딩, 함수포인터, 함수객체, 템플릿에 대하여 숙지하지 못하신분들은 꼭 다시 둘러보고 STL에 들어가도록 합시다!!






<작성자 - CODER_CJH>

<참고자료 - 뇌를 자극하는 C++STL>

'Programming Language > C++' 카테고리의 다른 글

8. vector 컨테이너(2)  (0) 2016.06.03
7. vector 컨테이너(1)  (0) 2016.06.03
5.함수 객체  (0) 2016.06.01
4. 함수 포인터  (1) 2016.06.01
3. STL에 필요한 주요 연산자 오버로딩(2)  (4) 2016.06.01

이번 시간에는 함수 객체에 대해 알아보도록 하겠습니다.

함수 객체란 ? 함수처럼 호출 가능한 클래스 객체입니다.

함수 객체는 함수처럼 사용할 수 있으면서도 상태를 가질 수 있기 때문에 STL은 함수보다 함수 객체를 선호합니다.

함수 객체를 함수처럼 동작하게 하려면 '()'연사자를 정의해야 합니다. 다시말해 '()'연사자를 오버로딩한 객체입니다.


간단한 예제를 통해 이해해 보도록 하겠습니다.


functor는 객체지만 함수처럼 호출할 수 있습니다.


그렇다면 일반함수보다 복잡해 보이는 함수 객체를 사용하는 이유가 무엇일가요?

그이유는 이렇습니다.

먼저 함수처럼 동작하는 객체이므로 다른 멤버 변수와 멤버 함수를 가질 수 있고 일반 함수에서 하지 못하는 지원을 받을 수 있습니다.

또한, 함수 객체의 서명이 같더라도 타입이 다르면 서로 전혀 다른 타입으로 인식합니다. 속도도 일반 함수보다 함수 객체가 빠릅니다. 

함수의 주소를 전달하여 콜백하는 경우 이 함수 포인터는 인라인될 수 없지만 함수 객체는 인라인될 수 있고, 컴파일가 쉽게 최적화할 수 있습니다.

이와같은 장점 때문에 함수 객체를 사용하게됩니다.


간단한 예제를 통해 함수 객체의 장점을 보겠습니다.


여기서 operator()(int n)함수는 클래스 내부에 정의되므로 암묵적으로 인라인 함수가 됩니다.



함수 객체에 대하여 이해가 가셨나요?

그렇다면 지금부터 함수 객체를 구현해보도록 하겠습니다.


첫번째로 less( < 연사자의 함수객체 )를 구현해보도록 하겠습니다.


Pred_less()함수는 두 정수를 입력받아 < 연산의 결과를 반환합니다.

1()은 함수객체로 두 정수를 입력받아 l.operator()()을 호출하고 결과를 반환합니다.

결과는 어떻게 될까요?


@

생각하신 결과가 맞으신가요? ㅎㅎ


greater( >연산자의 함수 객체)는 위의 less함수객체를 조금만 변형시키면 됩니다. 직접해보시기 바랍니다~^^



함수 객체의 포스팅은 여기서 마치도록하겠습니다.

다음시간에는 템플릿에 대해 알아보도록 하겠습니다.





<작성자 - CODER_CJH>

<참고자료 - 뇌를 자극하는 C++STL>



'Programming Language > C++' 카테고리의 다른 글

7. vector 컨테이너(1)  (0) 2016.06.03
6. 템플릿  (0) 2016.06.01
4. 함수 포인터  (1) 2016.06.01
3. STL에 필요한 주요 연산자 오버로딩(2)  (4) 2016.06.01
2. 연산자오버로딩(1)  (0) 2016.06.01

오늘은 함수 포인터에 대해 알아보겠습니다.

포인터는 뭘까요? 주소를 저장하는 메모리 공간의 이름입니다.

함수 포인터는 말그대로 함수의 주소를 저장하는 포인터입니다.


간단하게 예제를 통해 포인터 개념을 되새기고 넘어가도록 하겠습니다.


포인터 pn이  정수형변수 n을 가리키고 있는 것입니다.


그렇다면 본격적으로 함수 포인터 선언과 사용을 해보겠습니다.

함수 포인터는 함수 시그너처(함수의 반환 타입과 매개변수 리스트)와 같게 선언.

예를 들어 int func(int a,int b)인 함수의 함수 포인터는 int(*pf)(int ,int )와 같이 선언합니다.

예제를 통해 확인해 보도록 하겠습니다.

이 예제의 경우 어떤것이 출력 될까요?

바로 Print()함수의 주소입니다.

Print()함수의 시그너처가 void Print(int n)이므로 함수 포인터는 void (*pf)(int)로 선언합니다.


함수 포인터의 선언과 사용에 대해 알아 봤는데요. 지금부터 함수 포인터의 종류에 대하 알아보도록 하겠습니다.

들어가기 앞서 C++에는 세 가지의 함수 호출 방법이 있습니다.

1. 정적 함수 호출(정적 함수)

2. 객체로 멤버 함수 호출(멤버 함수)

3. 객체의 주소로 멤버 함수 호출(멤버 함수)

위 세 가지 방벙을 예제로 이해해 보겠습니다

Point객체 pt를 만들고 포인터p가 pt를 가리키고있내요.


다음으로 클라이언트 코드와 서버 코드에 대해 알아 보도록 하겠습니다.

서버 코드란 어떤 기능이나 서비스를 제공하는 코드측을 말합니다.

클라이언트 코드란 그기능을 제공받는 코드측을 말합니다.

일반적으로 서버는 하나지만 서버코드를 사용하는 클라이언트는 여러 개입니다.

예제를 통해 이해해 보도록 하겠습니다.

이해가시나요? main함수가 PrintHello()라는 기능을 제공받고 있으므로 클라이언트가됩니다.

반면 PrintHello()함수는 출력 기능을 제공하므로 서버가됩니다.


일반적으로 클라이언트 코드 측에서 서버를 호출하고 기능을 사용하지만, 때때로 서버가 클라이언트를 호출해야 하는 경우도 있습니다.

이처럼 클라이언트가 서버를 호출하면 콜(call)이라 하고 서버가 클라이언트를 호출하면 콜백(callback)이라 합니다.

STL의 많은 알고리즘도 콜백을 이용해 클라이언트 정책을 반영하고, 윈도의 모든 프로시저는 시스템이 호출하는 콜백입니다.

함수 포인터를 이용한 콜백 매커니즘을 구현 해보도록 하겠습니다.

클라이언트는 서버함수 For_each()를 세 번 호출합니다. 하지만, 세 번의 출력 결과는 클라이언트에 의해 결정됩니다. 출력 정책은 클라이언트만 알고 있습니다.

@ 

이처럼 콜백 메커니즘을 이용하면 알고리즘 적챙을 클라이언트에서 유연하게 바꿀 수 있게 서버를 더욱 추상화할 수 있습니다.


이제 함수 포인터에 대한 개념이 어느 정도 이해되셨나요? ㅎㅎ

저도 초보라 설명이 미숙한점 이해해 주시기 바랍니다.

다음 시간에는 함수 객체에 대하여 알아보도록 하겠습니다. 



<작성자 - CODER_CJH>

<참고자료 - 뇌를 자극하는 C++STL>

'Programming Language > C++' 카테고리의 다른 글

6. 템플릿  (0) 2016.06.01
5.함수 객체  (0) 2016.06.01
3. STL에 필요한 주요 연산자 오버로딩(2)  (4) 2016.06.01
2. 연산자오버로딩(1)  (0) 2016.06.01
1. STL에 들어가기 앞서...  (1) 2016.06.01

안녕하세요 이번시간에는 STL에 필요한 주요 연산자 오버로딩에 대해 배워보겠습니다.


첫번째로 함수 호출 연산자 오버로딩(()연산자)에 대해 알아 보겠습니다.

함수 호출 연산자 오버로딩은 객체를 함수처럼 동작하게 하는 연산자입니다.

C++에서 Print(10)이라는 함수 호출 문장은 다음 세 가지로 해석할 수 있습니다.

1. 함수호출 : Print가 함수 이름

2. 함수포인터 : Print가 함수 포인터

3. 함수 객체 : Print가 함수 객체

여기서 함수 호출 연산자를 정의한 객체를 함수 객체라 합니다.

예제를 통해 쉽게 이해해 보도록 하겠습니다.


두번쨰로 배열 인덱스 연산자 오버로딩([]연산자)에 대해 알아 보도록하겠습니다.

배열 인덱스 연산자 오버로딩을 사용하면 배열에 사용하는 []연산자를 객체에도 사용할 수 있습니다.

[]연산자 오버로딩은 일반적으로 많은 객체를 저장하고 관리하는 객체에 사용됩니다.

예제를 통해 쉽게 이해해 보도록 하겠습니다.

@

pt[0]는 pt.operator[](0)을 호출해 pt.x값을 반환 받습니다.

[]연산자 오버로딩은 일반적으로 컨테이너 객체에 사용됩니다. 컨테이너 객체가 곤리하는 내부 원소에 접근할 때 사용됩니다.



세번째로 ->연산자 오버로딩에 대해 알아보겠습니다.

예제를 보시겠습니다.

p1->Print()는 p1.operator->()함수를 호출해 ㅔ1 내부에 보관된 실제 포인터를 반환 받고 이 포인터를 이용해 실제 point의 멤버 함수를 호출합니다.


이상으로 연산자 오버로딩에 대한 포스팅을 마치겠습니다.

궁금하신점이나 오류가 있으면 댓글남겨주세요 ~

다음시간에 함수 포인터에 대해 다뤄보겠습니다.




<작성자 - CODER_CJH>

<참고자료 - 뇌를 자극하는 C++STL>

'Programming Language > C++' 카테고리의 다른 글

6. 템플릿  (0) 2016.06.01
5.함수 객체  (0) 2016.06.01
4. 함수 포인터  (1) 2016.06.01
2. 연산자오버로딩(1)  (0) 2016.06.01
1. STL에 들어가기 앞서...  (1) 2016.06.01

+ Recent posts