고급 포인터 주제

2025. 3. 28. 08:45Programming Languages/C++

6.5 고급 포인터 주제

6.5.1 포인터와 const

포인터와 const 키워드의 조합으로 다양한 상황을 표현할 수 있습니다:

#include <iostream>

int main() {
    int value = 42;
    int another = 100;
    
    // 1. 상수 포인터 (포인터 자체가 상수)
    int* const constPtr = &value;
    *constPtr = 50;  // 값 변경 가능
    // constPtr = &another;  // 오류: 포인터를 다른 주소로 변경 불가
    
    // 2. 상수에 대한 포인터 (가리키는 값이 상수)
    const int* ptrToConst = &value;
    // *ptrToConst = 60;  // 오류: 가리키는 값 변경 불가
    ptrToConst = &another;  // 다른 주소 가리키기 가능
    
    // 3. 상수에 대한 상수 포인터 (둘 다 불변)
    const int* const constPtrToConst = &value;
    // *constPtrToConst = 70;  // 오류: 값 변경 불가
    // constPtrToConst = &another;  // 오류: 주소 변경 불가
    
    std::cout << "value: " << value << std::endl;  // 50
    
    return 0;
}

6.5.2 함수 포인터

함수 포인터는 함수의 주소를 저장하고 호출할 수 있는 포인터입니다:

#include <iostream>
#include <string>

// 함수 원형
int add(int a, int b) {
    return a + b;
}

int subtract(int a, int b) {
    return a - b;
}

int multiply(int a, int b) {
    return a * b;
}

int divide(int a, int b) {
    return b != 0 ? a / b : 0;
}

int main() {
    // 함수 포인터 선언
    int (*operation)(int, int);
    
    // 함수 포인터에 함수 할당
    operation = add;
    std::cout << "덧셈 결과: " << operation(5, 3) << std::endl;  // 8
    
    operation = subtract;
    std::cout << "뺄셈 결과: " << operation(5, 3) << std::endl;  // 2
    
    operation = multiply;
    std::cout << "곱셈 결과: " << operation(5, 3) << std::endl;  // 15
    
    operation = divide;
    std::cout << "나눗셈 결과: " << operation(6, 3) << std::endl;  // 2
    
    // 함수 포인터 배열
    int (*operations[4])(int, int) = {add, subtract, multiply, divide};
    std::string opNames[4] = {"덧셈", "뺄셈", "곱셈", "나눗셈"};
    
    for (int i = 0; i < 4; i++) {
        std::cout << opNames[i] << " 결과: " << operations[i](10, 5) << std::endl;
    }
    
    return 0;
}

함수 포인터는 콜백, 전략 패턴, 플러그인 아키텍처 등에 유용합니다.

6.5.3 다차원 배열과 포인터

다차원 배열을 포인터로 다루는 방법:

#include <iostream>

int main() {
    // 2차원 배열
    int matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    
    // 포인터로 접근
    int (*ptr)[4] = matrix;  // 4개의 정수 배열에 대한 포인터
    
    // 첫 번째 행의 요소 출력
    for (int j = 0; j < 4; j++) {
        std::cout << ptr[0][j] << " ";  // 1 2 3 4
    }
    std::cout << std::endl;
    
    // 포인터 증가로 다음 행에 접근
    ptr++;
    for (int j = 0; j < 4; j++) {
        std::cout << ptr[0][j] << " ";  // 5 6 7 8
    }
    std::cout << std::endl;
    
    // 이중 포인터를 사용한 동적 2차원 배열 할당
    int rows = 3, cols = 4;
    int** dynamicMatrix = new int*[rows];
    
    for (int i = 0; i < rows; i++) {
        dynamicMatrix[i] = new int[cols];
        // 각 행 초기화
        for (int j = 0; j < cols; j++) {
            dynamicMatrix[i][j] = i * cols + j + 1;
        }
    }
    
    // 동적 2차원 배열 출력
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            std::cout << dynamicMatrix[i][j] << " ";
        }
        std::cout << std::endl;
    }
    
    // 동적 2차원 배열 해제 (순서 중요!)
    for (int i = 0; i < rows; i++) {
        delete[] dynamicMatrix[i];
    }
    delete[] dynamicMatrix;
    
    return 0;
}

6.5.4 멤버 포인터

클래스의 멤버 변수나 멤버 함수를 가리키는 포인터:

#include <iostream>
#include <string>

class Person {
public:
    std::string name;
    int age;
    
    Person(const std::string& n, int a) : name(n), age(a) {}
    
    void introduce() {
        std::cout << "안녕하세요, 제 이름은 " << name << "이고 " 
                  << age << "살입니다." << std::endl;
    }
    
    void celebrateBirthday() {
        age++;
        std::cout << "생일 축하합니다! 이제 " << age << "살이 되었습니다." << std::endl;
    }
};

int main() {
    // 멤버 변수 포인터
    std::string Person::*namePtr = &Person::name;
    int Person::*agePtr = &Person::age;
    
    // 멤버 함수 포인터
    void (Person::*introducePtr)() = &Person::introduce;
    void (Person::*birthdayPtr)() = &Person::celebrateBirthday;
    
    // 객체 생성
    Person person("홍길동", 25);
    
    // 멤버 변수 포인터 사용
    std::cout << "이름: " << person.*namePtr << std::endl;
    std::cout << "나이: " << person.*agePtr << std::endl;
    
    // 멤버 변수 포인터로 값 변경
    person.*namePtr = "김철수";
    person.*agePtr = 30;
    
    // 멤버 함수 포인터 사용
    (person.*introducePtr)();
    (person.*birthdayPtr)();
    
    // 포인터를 통한 멤버 접근
    Person* personPtr = &person;
    std::cout << "포인터를 통한 이름: " << personPtr->*namePtr << std::endl;
    (personPtr->*introducePtr)();
    
    return 0;
}

멤버 포인터는 일반 포인터보다 복잡하지만, 런타임에 클래스의 특정 멤버를 선택하는 등의 고급 기법에 유용합니다.

 

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

템플릿  (0) 2025.03.28
챕터6. 실습 문제  (0) 2025.03.28
참조  (0) 2025.03.28
동적 메모리 할당  (0) 2025.03.28
포인터의 기본  (0) 2025.03.28