C ++와 유사한 const를 언어로 가져 오는 데 어떤 문제가 있습니까?


17

C ++과 같은 const특정 실행이 아닌 캐스팅 과 같은 아이디어에 관심이 있습니다 const.

C #과 같은 const가 부족한 C #을 예로 들어 보자. 일반적인 이유는 사람과 시간이다. 또한 C # 팀은 constCLR 마케팅 의 C ++ 실행 을 살펴본 결과이 시점에서 충분했습니다 ( c # 및 const 매개 변수에 const 멤버 메소드가없는 이유 참조 : Svick 감사합니다). 경우 수 우리가 보다 더 이동 무엇입니까?

더 깊은 것이 있습니까? 예를 들어 다중 상속을 예로들 수 있습니다. 일반적으로 파악하기 어렵고 (사용자에게는) 다이아몬드 언어와 같이 언어에 추가되지 않습니다.

거기에 뭔가가 자연const그 언어를 피하기 위해 더 나은 것을 문제 포즈? const깊거나 얕을 지를 결정하는 것과 같은 것 ( const컨테이너가 있다는 것은 새로운 요소를 추가하거나 기존 요소를 변경할 수 없다는 것을 의미합니다. 요소가 참조 유형이면 어떻게됩니까)?

업데이트 : C #을 언급하면서 역사적 관점 const을 제시하면서 언어 의 잠재적 문제의 본질에 관심 이 있습니다.

이것은 언어의 도전이 아닙니다. 현재 추세 나 인기와 같은 요소를 무시하십시오. 기술적 인 문제에만 관심이 있습니다. 감사합니다.


3
제쳐두고 : 다중 상속은 파악하기 어려울 수 없지만 메소드 분석은 상당히 추악해질 수 있습니다. 순진한 깊이 우선 해상도는 빠르게 직관적이지 않습니다 ( " 다이아몬드 문제 "). C3 방법 확인 순서 ('96 출판)이 해결하지만 확실히 하지 쉽게 이해하기. 따라서 다중 상속을 불법화하는 것은 종종 합리적으로 보일 수 있습니다. 그러나 실제 문제는 Java가 C3 알고리즘보다 우선하고 C #이 Java를 지향한다는 것입니다.
amon

3
@amon 많은 사람들이 다중 상속이 D 프로그래밍 언어의 제작자와 같이 처음부터 갖고 싶은 기능이라고 생각하지 않습니다. 이는 논쟁의 가치가있는 복잡한 기능입니다. 효율적인 방식으로 구현하는 것은 매우 어렵고 컴파일러는이를 구현할 때 많은 버그가 발생하기 쉽습니다. 거의 모든 MI 값은 인터페이스 및 집계와 결합 된 단일 상속으로 처리 할 수 ​​있습니다. 남은 것은 MI 구현의 무게를 정당화하지 않습니다. (source)
jcora


2
심지어 없이 다중 상속을 할 수 있습니다 이미 따라서는 NP-완료하고, C #의 메소드 해상도 (또는 더 정확하게 과부하 해상도)와 같은 3-SAT 문제를 인코딩합니다.
Jörg W Mittag

1
@svick, 대단히 감사합니다. 이 질문에 대한 답변이 없었기 때문에 나는 문제의 본질에 초점을 맞추기 위해 문제의 본질에 초점을 맞추기 위해 문제를 크게 편집 할 자유를 얻었습니다. 왜냐하면 99 %는 "시간 + 사람 + 안티 C ++ 편향 + CLR ".
greenoldman

답변:


10

이것이 자격이되는지 표준 ML과 같은 기능적 언어에서는 기본적으로 모든 것이 변경되지 않습니다. 돌연변이는 일반적인 오류 ref유형을 통해 지원됩니다 . 따라서 int변수는 변경할 수 없으며 ref int변수는 ints 의 변경 가능한 컨테이너입니다 . 기본적으로 변수는 수학적 의미 (알 수 없지만 고정 된 값)의 실제 변수이고 refs는 명령형 프로그래밍 의미의 "변수"입니다. 즉, 읽고 쓸 수있는 메모리 셀입니다. (나는 그것들을 어사 인 이라고 부릅니다 .)

나는 문제 const가 두 가지 라고 생각한다 . 첫째, C ++에는 가비지 콜렉션이 없기 때문에 사소한 영속적 인 데이터 구조 가 필요합니다 . const 있어야 아직 불가능하다 ++ C에서 완전 불변의 값을 갖는 어떤 의미가 깊은합니다.

둘째, C ++ const에서는 옵트 아웃하지 않고 옵트 인해야합니다. 그러나 const무언가 를 잊어 버렸다가 나중에 고치면 @RobY의 답변에 언급 된 "const poisoning"상황 const이 발생하여 코드 전체에서 변경 사항이 연속적으로 발생합니다. const기본값 인 경우 const소급 적용되지 않습니다. 또한, const모든 곳에 추가해야 코드에 많은 노이즈가 추가됩니다.

필자가 따르는 주류 언어 (예 : Java)는 C와 C ++의 성공과 사고 방식에 따라 크게 형성되었다고 생각합니다. 가비지 수집에서도 대부분의 언어 수집 API는 변경 가능한 데이터 구조를 가정합니다. 모든 것이 변경 가능하고 불변성이라는 사실이 코너 케이스로 간주된다는 사실은 인기있는 언어의 근본적인 사고 방식에 대해 많은 것을 말해줍니다.

편집 : greenoldman의 의견을 반영한 후 나는 const데이터의 불변성에 대해 직접적인 것이 아니라는 것을 깨달았습니다 . const메소드에 인스턴스에 부작용이 있는지 여부를 메소드 유형으로 인코딩합니다.

돌연변이를 사용하여 참조 적으로 투명한 동작 을 수행 할 수 있습니다. 호출 될 때 다른 값을 연속적으로 반환하는 함수 (예 :에서 단일 문자를 읽는 함수)가 있다고 가정합니다 stdin. 캐시 / 메모리를 사용하여이 함수의 결과를 참조하여 투명한 값의 스트림을 생성 할 수 있습니다. 스트림은 값을 처음 검색하려고 시도 할 때 노드가 함수를 호출 한 다음 결과를 캐시하는 링크 된 목록입니다. 따라서 stdinconstains Hello, world!이면 첫 번째 노드의 값을 처음 검색하려고 할 때 하나를 읽고 char를 반환 H합니다. 이후에는을 (를) H호출하기위한 추가 호출없이 계속해서 돌아옵니다 char. 마찬가지로, 두 번째 노드는 읽기 것이다 char로부터stdin처음으로 값을 검색하려고하면 이번에는 e해당 결과를 리턴 하고 캐싱합니다.

여기서 흥미로운 점은 본질적으로 상태가 좋은 프로세스를 상태가없는 것으로 보이는 객체로 바꾸 었다는 것입니다. 그러나이를 달성하기 위해 객체의 내부 상태를 변경해야 (결과를 캐싱하여) 변이가 양성 이었습니다 . CharStream const스트림 불변 값처럼 동작 하더라도 우리를 만드는 것은 불가능 합니다. 이제 메소드 Stream와 인터페이스가 const있고 모든 함수가 기대 한다고 상상해보십시오 const Streams. 귀하는 CharStream인터페이스를 구현할 수 없습니다!

( 편집 2 : 분명히 우리가 부정 행위mutable할 수CharStream const 있는 C ++ 키워드 있습니다. 그러나이 허점은 const보증을 파괴 const합니다. 이제 그 방법을 통해 무언가가 돌연변이되지 않을 것이라고 확신 할 수는 없습니다 . 허점을 명시 적으로 요청해야하기 때문에 나쁘지만 여전히 명예 시스템에 전적으로 의존하고 있습니다.)

둘째, 고차 함수가 있다고 가정합니다. 즉, 함수를 인수로 다른 함수에 전달할 수 있습니다. constness는 함수 시그니처의 일부이므로 함수가 아닌 const함수에 함수가 아닌 함수를 인수로 전달할 수 없습니다 const. const여기서 맹목적으로 시행 하면 일반성이 상실 될 수 있습니다.

마지막으로, const객체를 조작 한다고해서 등 뒤의 외부 (정적 또는 전역) 상태 const가 변경되지 않는다는 보장은 없으므로 '보증은 처음에 나타나는 것만 큼 강력하지 않습니다.

부작용의 유무를 타입 시스템에 인코딩하는 것이 보편적으로 좋은 것이라는 것은 분명하지 않습니다.


1
+1 감사합니다. 불변의 객체는 C ++ const 이외의 것입니다 (더보기입니다). 그러나 C ++은 기본적으로 const를 가지고 var있으며 요청시 하나의 문제, 즉 깊이?
greenoldman

1
@greenoldman 좋은 지적입니다. C ++ const을 사용한 지 오래되었습니다. 비 const객체에 대한 참조를 가질 수 없다는 것을 잊었습니다 . 그럼에도 불구하고 나는 그것이 얕은 것을 갖는 것이 의미가 있다고 생각하지 않습니다 const. 요점은 const해당 참조를 통해 객체를 수정할 수 없다는 보장입니다. constconst참조 를 생성 하여 회피 하는 것이 허용되지 않는 이유는 const무엇입니까?
Doval

+1 :-) 업데이트에서 매우 흥미로운 문제 (비 / const 람다와 함께 생활하고 외부 상태와 관련하여 더 약한 문제), 나는 그것을 더 오래 소화해야합니다. 어쨌든, 귀하의 의견에 관해서는 마음에 사악한 것이 없습니다. 매우 반대로, 코드의 선명도를 높이기 위해 기능을 찾고 있습니다 (다른 하나 : null이 아닌 포인터). 여기에 동일한 카테고리가 있습니다 (적어도 그것은 나의 목적입니다)-나는 정의 func foo(const String &s)하고 이것은 신호 s가에서 변경되지 않을 것입니다 foo.
greenoldman

1
@greenoldman 확실히 호소력과 근거를 볼 수 있습니다. 그러나, 가능한 한 변하기 쉬운 상태를 피하는 것 외에 (문제와 같은 다른 불쾌한 것들 null과 상속 과 같은) 다른 문제에 대한 실질적인 해결책은 없다고 생각합니다 .
Doval

8

주요 문제는 프로그래머가 그것을 충분히 사용하지 않는 경향이 있기 때문에, 그들이 필요한 곳에 부딪 치거나 관리자가 나중에 const-correctness를 고치려고 할 때 큰 파급 효과가 있습니다. 당신은 여전히없이 완벽하게 좋은 불변 코드를 작성할 수 있습니다. const컴파일러는 그것을 강제하지 않으며 최적화하기가 더 어려울 것입니다. 어떤 사람들은 컴파일러가 도움이되지 않는 것을 선호합니다. 나는 그 사람들을 이해하지 못하지만 많은 사람들이 있습니다.

기능적 언어에서 거의 모든 것이 가능 const하며, 변경이 허용되는 경우는 거의 예외가 아닙니다. 이것은 동시성 및 공유 상태에 대한 쉬운 추론과 같은 몇 가지 장점이 있지만, 문화가 변하는 언어에서 온다면 익숙해집니다. 다시 말해, 원하지 const않는 것은 기술적 인 문제가 아니라 사람들의 문제입니다.


+1 감사합니다. 불변의 객체는 내가 찾고있는 것 이외의 것이지만 (C # 또는 Java에서는 불변의 객체를 만들 수 있습니다) 불변의 접근 방식을 사용하더라도 깊거나 얕은 지 여부를 결정해야합니다 (예 : 포인터 / 참조 컨테이너) 가리키는 객체 의 값 을 변경 하십시오 ). 하루가 지나면 주요 문제가 기본값으로 설정된 것으로 보이며 새 언어를 디자인 할 때 쉽게 해결할 수 있습니다.
greenoldman

1
+1 lolz @ "일부 사람들은 컴파일러가 도움이되지 않는 것을 선호합니다. 그 사람들을 이해하지 못하지만 많은 사람들이 있습니다."
Thomas Eding

6

단점은 다음과 같습니다.

  • "const poisoning"은 const 선언이 const를 사용하도록 이전 또는 다음 선언을 강제 할 수 있고 const를 사용하여 이전 선언 다음에 선언을 할 수있는 경우 문제입니다. 당신이 통제 할 수 없다면 나쁜 장소에 갇힐 수 있습니다.

  • 절대 보증은 아닙니다. const가 참조 만 보호하지만 어떤 이유로 든 기본 값을 보호 할 수없는 경우가 있습니다. C에서도 const가 얻을 수없는 가장자리 사례가있어 const가 제공하는 약속을 약화시킵니다.

  • 일반적으로 업계의 정서는 강력한 컴파일 타임 보장에서 벗어나고 있지만 많은 편안함을 가져다 줄 수 있습니다. 오후에는 const 중독으로 인해 코드베이스의 66 %를 만지는 데 일부 파이썬 guy는 완벽하게 작동하고, 잘 설계되고, 잘 테스트되고, 완벽하게 작동하는 10 개의 Python 모듈 10 개를 출시했습니다. 그리고 그는 해킹을하지도 않았습니다.

어쩌면 문제는 아마도 어떤 전문가조차도 당신이 새로운 언어를 채택하려고 할 때 애매 모호하게 할 수있는 논란의 여지가있는 기능을 수행하는 이유 일 것입니다.

편집 : 짧은 대답, 새로운 언어는 채택하기 위해 가파른 언덕을 가지고 있습니다. 디자이너들은 실제로 채택하기 위해 어떤 기능이 필요한지 열심히 생각해야합니다. 예를 들어 가십시오. Google은 Conan-the-Barbarian 스타일의 디자인을 선택하여 가장 심오한 종교적 전투를 무너 뜨 렸으며, 실제로 내가 본 것보다 언어가 더 좋다고 생각합니다.


2
두 번째 글 머리 기호가 올바르지 않습니다. C ++에는 레퍼런스 / 포인터 wrt를 선언하는 3/4 가지 방법이 있습니다. constness : int *가변 값에 대한 int const *가변 포인터, int * constconst 값에 대한 가변 포인터, 가변 값에 대한 int const * constconst 포인터 , const 값에 대한 const 포인터
phresnel

감사합니다. 나는 마케팅이 아닌 본성에 대해 물었다 ( "업계가 멀어짐"은 C ++와 같은 본성이 아니다 const). 따라서 나는 "이 질문에 대해"관련이없는 "이유"라고 생각한다. const중독에 대해 -예를 들어 줄 수 있습니까? AFAIK이 장점이므로 무언가를 전달 const하면 그대로 유지 const됩니다.
greenoldman

1
그것은하지 않습니다 const문제가 있지만, 정말 유형을 변경 - 당신이 무엇이든, 그것은 항상 문제가 될 것입니다. 통과를 고려한 RichString다음 더 나은 합격을 실현하십시오 String.
greenoldman

4
@RobY : 나는 당신이 후자이전으로 무엇을 다루고 있는지 잘 모르겠습니다 . 그러나 오후에 코드를 살펴본 후에는 하향식이 아닌 상향식이 아닌 상향식을 수정해야한다는 것을 배워야합니다. 즉, 가장 안쪽 단위로 시작하여 작업을 진행해야합니다. 어쩌면 당신의 유닛이 충분히 고립되어 있지 않고, 단단히 결합되어 있거나, 내부 시스템의 먹이가되었습니다.
phresnel

7
"const poisoning"은 실제로 문제가되지 않습니다. 실제 문제는 C ++의 기본값이 non- const입니다. 선택하지 const말아야 할 것이 아니라 너무 쉬운 일이 아닙니다 const.
Doval

0

const언어 를 추가하는 데 철학적 인 문제 가 있습니다. const클래스에 선언 하면 클래스를 변경할 수 없습니다. 그러나 클래스는 메소드 (또는 뮤 테이터)와 결합 된 변수 세트입니다. 우리는 일련의 메소드 뒤에 클래스의 상태를 숨겨 추상화를 달성합니다. 클래스가 상태를 숨기도록 설계된 경우 외부에서 해당 상태를 변경하려면 뮤 테이터가 필요하지만 const더 이상 은 아닙니다 . 따라서 const불변 인 클래스 에만 선언 할 수 있습니다. 그래서const 클래스 (또는 선언하려는 유형 const)가 사소한 시나리오에서만 가능합니다 ...

그래서 우리는 필요합니까 const어쨌든 합니까? 나는 그렇게 생각하지 않습니다. const좋은 디자인이라면 쉽게 할 수 있다고 생각합니다 . 필요한 데이터와 위치, 데이터 대 데이터 메서드 및 I / O, 네트워크, 뷰 등에 필요한 추상화는 다음과 같습니다. 그러면 자연스럽게 상태를 처리하는 모듈과 클래스가 나뉘며 메서드와 상태가 필요없는 불변 클래스.

필자는 저장, 변환 및 그릴 수있는 큰 지방 데이터 객체에서 대부분의 문제가 발생한다고 생각합니다. 예를 들어 렌더러에 전달하려고합니다. 따라서 데이터 내용이 큰 데이터 개체에 비해 너무 비싸기 때문에 데이터 내용을 복사 할 수 없습니다. 그러나 어느 쪽이든 변경하기를 원하지 않으므로 const생각하는 것이 필요합니다 . 컴파일러가 설계 결함을 파악하도록하십시오. 그러나 이러한 객체를 불변 데이터 객체로만 분할하고 담당 모듈에서 메소드를 구현하면 포인터를 전달하고 (만) 불변성을 보장하면서 데이터로 수행하려는 작업을 수행 할 수 있습니다.

C ++에서 일부 메소드 const를 선언하고 다른 메소드에서 선언하지 않는 것이 가능하다는 것을 알고 있습니다. 그리고 얼마 후 캐시가 필요하고 게터가 객체를 변경하고 (게으른로드 때문에) const더 이상 없습니다. 그러나 이것이이 추상화의 요점입니까? 각 호출에서 어떤 상태가 변경되는지 알 수 없습니다.


1
"따라서 const는 클래스 (또는 const를 선언하려는 유형)가 사소한 시나리오에서만 가능합니다 ..." 영구 데이터 구조 는 불변이며 사소하지 않습니다. C ++에서는 거의 모든 인스턴스가 여러 인스턴스간에 내부 데이터를 공유하고 C ++에는 가비지 수집 기능이 없기 때문에 C ++에서 볼 수 없습니다. "좋은 디자인을 가지고 있다면 const없이 쉽게 할 수 있다고 생각합니다." 불변의 값은 코드를 추론하기가 훨씬 간단합니다.
Doval

+1 감사합니다. "클래스에 const 선언"에 대해 설명해 주시겠습니까? 클래스를 const로 설정 했습니까? 그렇다면 C ++ const는 뷰처럼 작동합니다. 클래스가 아닌 객체 옆에 const를 선언 할 수 있습니다 (또는 C ++ 11에서 변경된 것). 또한 다음 단락과 단어 "쉽게"에 문제가 있습니다. C #에서 C ++-const에 대한 좋은 질문이 있으며 관련 작업의 양이 가장 중요합니다-모든 유형의 constC ++ 의미 ) 모든 속성에 대해 인터페이스를 정의해야합니다.
greenoldman

1
"클래스"에 대해 이야기 할 때 실제로 "클래스의 인스턴스"를 의미합니까? 이것이 중요한 차이점이라고 생각합니다.
svick
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.