불변과 const의 차이점


28

나는 종종 용어를 본 적이 immutableconst같은 의미로 사용. 그러나 내 (작은) 경험에서 두 가지는 코드에서 만드는 '계약'에서 크게 다릅니다.

불변은이 객체 변경 되지 않을 것이라는 계약을합니다 (예 : Python 튜플, Java 문자열).

Const는이 변수 의 범위에서 수정되지 않을 것이라고 계약을 맺습니다 (예 : C / C ++ 키워드와 같이이 기간 동안 객체에 대해 다른 스레드가 수행 할 수있는 작업에 대한 약속은 없습니다).

언어가 단일 스레드 (PHP)이거나 선형 또는 고유 한 타이핑 시스템 (Clean, Mercury, ATS)을 가지고 있지 않는 한, 둘은 동일하지 않습니다.

먼저,이 두 개념에 대한 나의 이해가 정확합니까?

둘째, 차이가 있다면 왜 거의 독점적으로 상호 교환 적으로 사용됩니까?


1
const모든 언어에 존재하는 것은 아니며 모든 언어에는 변이성과 불변성이 존재하지 않기 때문에이 언어를 아고 니스트 하게 만드는 것은 적용 할 수 없습니다. 이러한 개념이 적용되는 경우에만 언어에 따라 다릅니다 .

2
관련 권장 자료 : 불변성 종류 (몇 가지 C # 예제이지만 언어에 구애받지 않음) 누군가 Eric Lippert에게 메달을 주었다.

답변:


14

이 차이가 가장 중요한 C ++에 대해 이야기하겠습니다.

올바르게 알 수 있듯이 불변 은 객체가 생성 된 후에는 전혀 변경 될 수 없음을 의미합니다. 이 생성은 물론 런타임에 발생할 수 있습니다. 즉, const객체가 반드시 컴파일 타임 상수는 아닙니다. C ++에서 (1)과 (2) 또는 (3)이 충족되면 객체를 변경할 수 없습니다.

  1. 멤버 함수에 mutable의해 변경된 멤버가 선언되지 않았습니다.const

  2. 선언 const

  3. const멤버 함수는 멤버 를 변경하기 위해 자격 const_cast을 제거 하는 데 사용하지 않습니다.const

그러나 액세스 수정자를 고려할 수도 있습니다. 작업이 내부적으로 인스턴스를 변경하지만 퍼블릭 인터페이스를 통해 관찰 가능한 인스턴스의 상태에 영향을 미치지 않으면 객체는“논리적으로 불변”입니다.

따라서 C ++는 변경 불가능한 객체를 만드는 데 필요한 도구를 제공하지만 C ++의 모든 것과 마찬가지로 도구는 최소한으로 충분하며 실제로 사용하기 위해 부지런해야합니다. 인스턴스 상태는 반드시 인스턴스 멤버 변수에 국한되는 것은 아닙니다. C ++은 참조 투명성을 강화하는 방법을 제공하지 않기 때문에 전역 또는 클래스 상태도 포함 할 수 있습니다.

constC ++에는 참조와 포인터를 규정하는 또 다른 기능이 있습니다. const참조 비 참조 할 수 const개체. 객체가 non-으로 선언 된 경우에만 참조를 const_cast통해 객체를 변경하는 데 사용 하는 것이 합법적입니다 (일반적으로 필요하거나 권장되지 는 않음) .constconst

int        i = 4;         // Non-const object.
const int* p = &i;        // const pointer.

*const_cast<int*>(p) = 5; // Legal.

물론 const객체 를 변경하는 것은 정의되지 않은 동작입니다 .

const int  i = 4;         // const object.
const int* p = &i;        // const pointer.

*const_cast<int*>(p) = 5; // Illegal.

19

키워드 "final"이 "const"를 나타내는 Java에 대해서는 다음을 고려하십시오.

final Person someone = new Person();

이것은 someone다른 Person 객체를 절대로 참조 할 수 없음을 의미 합니다. 그러나 여전히 추천 된 사람의 세부 정보를 변경할 수 있습니다. 예 :someone.setMonthlySalary(10000);

그러나 someone"Immutable"객체 인 경우 다음 중 하나에 해당합니다. (a) 이름이 지정된 메서드가 없습니다. setMonthlySalary (b) setMonthlySalary를 호출하면 항상 다음과 같은 예외가 발생합니다.UnsupportedOperationException


10

불변 개체는 생성 후 상태가 변경되지 않는 개체입니다. 예를 들어;

string prefix = "Pre";
string postfix = "Post";
string myComplexStr = prefix + postfix;

이 예제에서 myComplexStr 객체는 변경할 수 없지만 값이 계산되므로 일정하지 않습니다. 그리고 문자열이고 정적 길이 속성을 가지고 변경할 수 없으므로 변경할 수 없습니다.

Const 객체는 일반적으로 Pi, "USA", "StackOverflow.com", 포트 번호 등과 같이 값이 컴파일 전에 알려진 실제 상수를 식별하는 데 사용됩니다.

이러한 관점에서 Const는 값이 프로그램에 의해 계산되지 않기 때문에 변경 불가능한 객체와 다릅니다.

그러나 C ++에서 "const"키워드에 대해 이야기하고 있다면 "const"가 불변의 객체를 만드는 데 사용된다고 말할 수 있습니다.


1
C ++의 const는 변경 불가능한 객체를 만들지 않으며 액세스 수준 일뿐입니다.
클라 임

"const double pi = 3.14"가 어떻게 변하지 않는지 설명 할 수 있습니까?
Mert Akcakaya

그것은 그것이 어디에 있는지에 달려 있습니다. "double * p_pi = const_cast <double *> (& pi); * p_pi = 42;"라고 말하겠습니다. 예를 들어. 그런 다음 pi가 전역 공간이나 네임 스페이스에 있으면 세그먼테이션 오류가 발생하지만 정의되지 않은 동작이며 특정 오류가 아니라고 생각합니다. pi가 런타임에 사용 가능하고 정적이 아닌 객체의 멤버 인 경우 pi == 42를 얻습니다. C ++의 const는 데이터 불변성이 아닌 액세스 수준, 의미 적에 관한 것이므로 변경 가능을 사용할 수도 있습니다. C ++에서는 달성하기가 거의 불가능합니다. "시뮬레이션"만 할 수 있습니다. const는 변경할 수 없습니다.
Klaim

1
@Klaim constIIRC는 할당 된 위치에 관계없이 정의되지 않은 동작을 변경합니다. 정의되지 않은 동작은 특정 오류가 발생하는 것보다 나쁩니다 . 그것은 더 이상 C ++을 사용하지 않는다는 것을 의미합니다. C ++은 const값 을 변경할 수있는 수단을 제공하지 않습니다 ( mutable물론 멤버를 제외하고 는 중요하지 않습니다). 특정 구현이 허용하는 것은 또 다른 문제입니다. (최적화로 컴파일하면 가져온 스턴트는 pi대체 된 식을 사용하여 이후 표현식에 영향을 미치지 않습니다 .)

"C ++의 const는 불변 개체를 만들지 않습니다"는 여전히 자신의 답변에 명시된 것처럼 전역 상수를 생성하기 때문에 여전히 잘못되었습니다. 키워드는 물론 어떤 수준에서 의미 론적입니다. 그렇지 않으면 정의되지 않은 동작을 사용하기를 간절히 원한다면 항상 수동으로 메모리 셀의 전압을 변경하고 불변의 객체 값을 변경할 수 있습니다.
Mert Akcakaya

8

먼저,이 두 개념에 대한 나의 이해가 정확합니까?

예. 그러나 두 번째 질문은 이러한 차이점을 이해하지 못한다는 것을 보여줍니다.

둘째, 차이가 있다면 왜 거의 독점적으로 상호 교환 적으로 사용됩니까?

constC ++ 에서는 불변성이 아닌 액세스 수준 ( "읽기 전용"을 의미)에만 사용됩니다 . 액세스 자체가 데이터와 완전히 분리되어 있음을 의미합니다. 예를 들어 일부 데이터를 조작 한 다음 const 참조를 통해 노출 할 수 있습니다. 액세스는 읽기 전용이지만 모든 데이터가 변경 가능하므로 데이터 자체입니다.

const는 액세스 제한 만 보장하지만 불변성은 (예를 들어 D와 같이) 객체 수명의 어느 단계에서나 데이터를 변경할 수있는 방법을 암시하지 않습니다 .

이제 const 이외의 다른 방법으로 일부 데이터에 액세스 할 수 없도록하여 C ++에서 불변성을 시뮬레이트 할 수 있으며 데이터가 초기화 된 후 더 이상 건드리지 않도록해야합니다. 그러나 데이터를 불변으로 표시하면 D와 같은 언어가 제공하므로 강력한 보장은 아닙니다. 이 언어는 해당 데이터를 수정하는 작업을 전혀 수행 할 수 없도록하는 반면, C ++에서는 실제로 필요한 경우 const 캐스팅 및 변경을 통해 데이터를 변경할 수 있습니다.

결국, 동일한 보장을 전혀 제공하지 않기 때문에 전혀 동일 하지 않습니다.


3

자바 스크립트의 핵심 단어를 말하기 constObject.freeze

const바인딩에variables 적용됩니다 . 변경 불가능한 바인딩을 작성하므로 새 값을 지정할 수 없습니다.

Object.freeze객체 값에서 작동합니다. 객체를 불변으로 만듭니다 . 즉, 속성을 변경할 수 없습니다.


0

C ++에서는 동일합니다. const메모리에 객체가 있고 해당 메모리에 쓸 수있는 OS 권한이 있으면 객체 를 변경할 수 있습니다 .


1
사실 그 인수의 에 대한 동일한되는 그들 : C ++ 단순히 어떤 불변의 키워드 또는 언어 지원이 없습니다. 또한 프로그래머가 제정신으로 언어를 사용한다고 가정합니다. 그렇지 않으면 const도 절대 가치가 없습니다.
K.Steff

1
@ K.Steff-const가 제공 한 것 외에는 C ++에 추가적인 불변성이 없다고 말하는 것이 좋습니다
Martin Beckett

:)
K.Steff

C ++에서는 전혀 동일하지 않습니다. const가 "읽기 전용"액세스 수준이므로 데이터가 변경 불가능하다는 의미는 아닙니다. 대부분의 경우 C ++에서 무시할 수 있습니다.
Klaim

0

C, C ++ 및 관련 언어에서 const 객체와 참조 또는 상수 참조 객체에 대한 포인터 사이에는 차이가 있습니다.

상수 객체를 수정하려고하면 정의되지 않은 동작이 발생합니다. (당신은 할 수 시도 , 해당 주소를 복용 const가 아닌 포인터에 주소를 캐스팅 한 다음 const가 아닌 포인터가 객체를 수정하는 것을 이용하여, 예를 들어 일정한 객체를 수정).

반면에 상수 포인터 또는 참조는 컴파일러에게이 포인터 또는 참조를 사용하여 객체를 수정할 수 없음을 알려줍니다. 포인터 또는 참조를 캐스트하고 오브젝트를 수정하려고 시도 할 수 있습니다. 개체 자체가 일정하면 나쁜 일이 발생합니다. 객체가 실제로 일정하지 않은 경우 변경됩니다. 이것은 물론 코드 사용자를 혼란스럽게하고 버그를 일으킬 수 있습니다.

C에서 "Hello"와 같은 문자열 리터럴을 사용하는 경우 5 개의 문자와 후행 0 바이트는 실제로 일정하지만 상수가 아닌 포인터를 얻습니다. 비 const 포인터를 사용하여 객체를 변경하는 것은 매우 나쁜 생각입니다.

C에서는 "const limit"포인터를 가질 수 있습니다. 즉, 대상이 일시적으로 일정하다는 의미입니다. "const restrict"포인터가 범위 내에있는 동안 어떤 방법으로도 객체를 수정하면 정의되지 않은 동작이 발생합니다. 이 포인터를 통해 객체를 변경하지 못하게하는 const 포인터보다 강력합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.