{{ label!='' ? 'Label : ' : (q!='' ? '검색 : ' : '전체 게시글') }} {{ label }} {{ q }} {{ ('('+(pubs|date:'yyyy-MM')+')') }}

[C++] The C++ Programming Language: 7. Pointers, Arrays, and References (4) - Pointers and References

 7.7.4 Pointers and References

  포인터와 참조는 복사 없이 서로 다른 공간에서 같은 객체에 접근할 수 있는 메커니즘들입니다. 이를 그림으로는 다음과 같이 나타낼 수 있죠:

  이 둘은 각자 장단점이 존재합니다.

  만약 여러분이 '어떤 객체를 참조할 것인지'를 변경하고 싶다면, 포인터를 사용하세요. 여러분들은 =, +=, -=, ++, --를 포인터 변수에 사용할 수 있습니다:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void fp(char∗ p)
{
    while (∗p)
    cout << ++∗p;
}

void fr(char& r)
{
    while (r)
        cout << ++r; // oops: increments the char referred to, not the reference
    // near-infinite loop!
}

void fr2(char& r)
{
    char∗ p = &r; // get a pointer to the object referred to
    while (∗p)
        cout << ++∗p;
}
cs

 

 반대로, 여러분이 해당 이름이 언제나 같은 객체를 참조하길 바란다면, 참조자를 활용하세요:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
template<class T> class Proxy { // Proxy refers to the object with which it is initialized
    T& m;
public:
    Proxy(T& mm) :m{mm} {}
    // ...
};

template<class T> class Handle { // Handle refers to its current object
    T∗ m;
public:
    Proxy(T∗ mm) :m{mm} {}
    void rebind(T∗ mm) { m = mm; }
    // ...
};
cs


  만약 여러분이, 참조하는 객체에 사용자 정의(오버로딩된) 연산자를 사용하고 싶다면, 참조자를 활용하세요:

1
2
3
4
5
6
7
Matrix operator+(const Matrix&, const Matrix&); // OK
Matrix operator−(const Matrix∗, const Matrix∗); // error : no user-defined type argument

Matrix y, z;
// ...
Matrix x = y+z; // OK
Matrix x2 = &y−&z; // error and ugly
cs

  포인터와 같은 내장 자료형에 대한 다항 연산자를 재정의하는 것은 불가능합니다.


  만약 여러분이, 어떤 객체를 참조하는 컬렉션을 얻고 싶다면, 포인터를 사용해야만 합니다:

1
2
3
4
5
int x, y;
string& a1[] = {x, y}; // error : array of references
string∗ a2[] = {&x, &y}; // OK
vector<string&> s1 = {x , y}; // error : vector of references
vector<string∗> s2 = {&x, &y}; // OK
cs

  

  C++가 프로그래머에게 참조 혹은 포인터를 강제하는 영역이 아니라면, 그곳은 미학의 영역입니다. 이상적으로는 가독성을 최대화하고 에러의 확률을 최소화하는 선택을 하는 것이 좋겠죠.

  만약 여러분이 "no value"의 개념이 필요하다면, 포인터는 nullptr를 제공합니다. 이에 상응하는 "null reference"(참조자 개념에서의 null-옮긴 이)는 없습니다. 만약 "no value"의 개념이 필요하다면, 포인터를 활용하는 것이 적절합니다:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void fp(X∗ p)
{
    if (p == nullptr) {
    // no value
    }
    else {
    // use *p
    }
}

void fr(X& r) // common style
{
    // assume that r is valid and use it
}
cs

  만약 여러분이 참조자로서 "null reference"를 정의하고 싶다면, 다음과 같이 적절한 "null reference"를 생성한 뒤 코드를 작성해야 합니다:

1
2
3
4
5
6
7
8
9
void fr2(X& r)
{
    if (&== &nullX) { // or maybe r==nullX
        // no value
    }
    else {
        // use r
    }
}
cs

  확실히, 여러분은 적절하게 정의된 nullX가 필요합니다. 이러한 스타일은 별로 관용적이지 않습니다. 또한 저 역시 추천하지 않습니다. 프로그래머는 참조가 유효하다고 가정해도 됩니다. 유효하지 않은 참조를 생성할 수는 있습니다만, 이를 하기 위해서는 꽤 노력해야 합니다:

1
2
3
char∗ ident(char ∗ p) { return p; }

char& r {∗ident(nullptr)}; // invalid code
cs

  예를 들어 위 코드는 유효한 C++ 코드가 아닙니다. 여러분 코드의 현재 구현이 이러한 문제를 잡지 않는다고 해도, 저렇게는 코드를 작성하지 마세요.

댓글

이 블로그의 인기 게시물

[코딩의탑] 4층: 툰 쉐이딩

[코딩의탑] 3층: 바다 렌더링

[코딩의탑] 5층: 포탈(Portal), 더 나아가기