Program Language/C & C++

[C++] Pointer & const

야곰야곰+책벌레 2021. 12. 29. 13:16
728x90
반응형

C++에서 상수를 나타내기 위해서 두 가지 방법을 제공한다.

constexpr : 컴파일 시 평가
const : 수행 중 수정 불가

기본적으로 constexpr의 역할은 compile-time 평가를 가능하게 하고 보장하는 반면, const의 주요 역할은 인터페이스에서 불변성을 지정하는 것이다. 여기서는 인터페이스의 사양에 대해 주로 다룬다.

 

많은 객체들은 초기화 이후 값이 변경되지 않는다.

  • Symbolic constants는 코드에서 직접 literal을 사용하는 것보다 유지 관리가 더 쉬운 코드로 이어진다.
  • 많은 포인터들이 읽히지만 결코 쓰지 않는 경우가 많다.
  • 대부분의 함수 파라미터들은 읽히지만 쓰지는 않는다.

초기화 후 이러한 불변성 개념을 표현하기 위해 객체 정의에 const를 추가할 수 있다.

const int model = 90; // model is a const
const int v[] = { 1, 2, 3, 4 }; // v[i] is a const
const int x; // error : no initializer

const로 선언된 객체는 할당할 수 없으므로 초기화해야 한다. const를 선언하면 해당 범위 내에서 값이 변경되지 않는다.

void f()
{
	model = 200; // error
	v[2] = 3; // error
}

const는 타입을 수정한다. 상수를 할당하는 방법을 지정하는 대신 객체를 사용할 수 있는 방법을 제한한다.

void g(const X∗ p)
{
	// can’t modify *p here
}

void h()
{
	X val; // val can be modified here
	g(&val);
	// ...
}

포인터를 사용할 때 포인터 자체와 가리키는 객체의 두 가지 객체가 관련된다. const로 포인터를 선언하는 '접두사'는 포인터가 아닌 객체를 상수로 만든다. 가리키는 객체가 아니라 포인터 자체를 상수로 선언하기 위해 일반 *대신 선언자 연사자 *const를 사용한다.

void f1(char∗ p)
{
	char s[] = "Gorm";
	const char∗ pc = s; // pointer to constant
	pc[3] = 'g'; // error : pc points to constant
	pc = p; // OK
	char ∗const cp = s; // constant pointer
	cp[3] = 'a'; // OK
	cp = p; // error : cp is constant
	const char ∗const cpc = s; // const pointer to const
	cpc[3] = 'a'; // error : cpc points to constant
	cpc = p; // error : cpc is constant
}

포인터를 상수로 만드는 선언자 연산자는 *const다. const* 선언자 연산자가 없으므로 *앞에 붙이는 const는 기본 유형의 일부로 간주된다.

char ∗const cp; // const pointer to char
char const∗ pc; // pointer to const char
const char∗ pc2; // pointer to const char

어떤 사람들은 이러한 선언을 오른쪽에서 왼쪽으로 읽는 것이 도움이 된다고 말한다. 예를 들어 "cp는 char에 대한 const 포인터다", "pc2는 char const에 대한 포인터다". 하나의 포인터를 통해 액세스 할 때 상수인 개체는 다른 방법으로 액세스 할 때 변수일 수 있다. 이것은 특히 함수 인수에 유용하다. 포인터 인수 const를 선언하면 함수가 가리키는 객체를 수정할 수 없게 된다.

const char∗ strchr(const char∗ p, char c); // find first occurrence of c in p
char∗ strchr(char∗ p, char c); // find first occurrence of c in p

첫 번째는 요소를 수정하면 안 되는 문자열에 사용되며 수정을 허용하지 않는 const에 대한 포인터를 반환한다. 두 번째는 변경 가능한 문자열에 사용된다. const가 아닌 변수의 주소를 상수 포인터에 할당할 수 있다. 그러나 상수의 주소는 무제한 포인터에 할당할 수 없다. 이렇게 하면 객체의 값이 변경될 수 있기 때문이다.

void f4()
{
	int a = 1;
	const int c = 2;
	const int∗ p1 = &c; // OK
	const int∗ p2 = &a; // OK
	int∗ p3 = &c; // error : initialization of int* with const int*
	∗p3 = 7; // tr y to change the value of c
}

const에 대한 포인터에 대한 제한을 명시적으로 제거하는 것은 가능하지만 일반적으로 현명하지는 않다.

728x90
반응형

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

[C++] 참조(references)  (0) 2021.12.29
[C++] pointer & 소유권  (0) 2021.12.29
[C++] 포인터(Pointer)  (0) 2021.12.23
[C++] 별칭  (0) 2021.12.16
[C++] 객체와 값  (0) 2021.12.16