const 정확성에 나를 판매


133

const를 가능한 한 자주 사용하는 것이 권장되는 이유는 무엇입니까? const 사용하는 것이 C ++의 도움보다 더 고통 스러울 수 있습니다. 그러나 다시 한 번 파이썬 관점 에서이 문제를 해결하려고합니다. 변경하고 싶지 않은 경우 변경하지 마십시오. 그래서 그와 함께 몇 가지 질문이 있습니다.

  1. 무언가를 const로 표시 할 때마다 오류가 발생하고 다른 함수를 const로 변경해야합니다. 그런 다음 다른 곳에서 다른 기능 을 변경해야합니다 . 이것이 경험으로 더 쉬워지는 것입니까?

  2. const 사용의 이점이 실제로 문제를 보완하기에 충분합니까? 객체를 변경하지 않으려면 객체를 변경하지 않는 코드를 작성하지 마십시오.

이 시점에서 정확성과 유지 관리 목적으로 const를 사용하는 이점에 가장 중점을 두었지만 성능에 대한 아이디어를 갖는 것도 좋습니다.


1
8 년 된 회고 적이지만 .. 코드를 100 배 빠르게 올리는 것은 어떻습니까?
lorro

1
여기에서 내 답변을 확인하십시오 (관련 질문, 같은 답변을 드리겠습니다) : stackoverflow.com/questions/42310477/… BTW : 사랑합니다const
Gines Hidalgo

답변:


158

:이 "CONST 정확성"에 결정적인 기사입니다 https://isocpp.org/wiki/faq/const-correctness .

간단히 말해 const를 사용하는 것이 좋습니다.

  1. 의도하지 않은 변수를 실수로 변경하는 것을 방지합니다.
  2. 실수로 변수를 할당하는 것을 방지하고
  3. 컴파일러가이를 최적화 할 수 있습니다. 예를 들어,

    if( x = y ) // whoops, meant if( x == y )

동시에 컴파일러는 변수 / 함수의 상태를 항상 정확히 알고 있기 때문에보다 효율적인 코드를 생성 할 수 있습니다. 엄격한 C ++ 코드를 작성하는 경우 좋습니다.

const-correctness를 일관되게 사용하는 것이 어려울 수 있지만, 최종 코드는 더 간결하고 프로그래밍하기에 안전합니다. 많은 C ++ 개발을 수행하면이 이점이 빠르게 나타납니다.


나는 항상 const 값을 자유롭게 캐시 할 수 있다고 가정하여 많은 동시성 문제를 피하거나 속도를 향상시킵니다. 그게 사실입니까?
Phil H

3
확실한. const변수 컴파일러가 변수의 전체 의도와 사용을 알고 있기 때문에보다 최적의 코드를 생성 할 수 있다는 점에서 속도를 향상시킬 수 있습니다. 차이점을 알 수 있습니까? 글쎄, 그것은 당신의 신청에 대해 논쟁의 여지가 있습니다. 동시성에 관한 한, const-variables는 읽기 전용이므로 값이 항상 동일하기 때문에 해당 변수에 대한 독점 잠금이 필요하지 않습니다.
Jordan Parmer

4
C ++ 11부터 표준 라이브러리는 const스레드 안전을 의미하고 이러한 방식으로 자신의 코드를 처리 한다고 가정 하면 가능한 멀티 스레딩 문제를 쉽게 확인할 수 있으며 API 사용자에게 API 보증을 제공하는 쉬운 방법입니다.
pmr

3
나를 위해 const 정확성의 가장 큰 부가 가치 중 하나는 포인터가 함수에 의해 절대 변경되지 않는 데이터를 참조 할 때 함수 프로토 타입을 보는 것만으로도 알 수 있다는 것입니다 (예 : 입력 전용).
cp.engr

1
논리적 이고 물리적 인 의미 가 있다는 것을 잊지 마십시오 . 변경 가능한 것으로 표시된 포함 된 집계 개체는 변경 될 수 있지만이를 표시하는 것은 포함하는 개체의 논리적 구성과 관련이 없음을 의미합니다.
Adrian

128

const 정확성이 당신을 보호 할 수있는 일반적인 오류가있는 코드는 다음과 같습니다.

void foo(const int DEFCON)
{
   if (DEFCON = 1)     //< FLAGGED AS COMPILER ERROR! WORLD SAVED!
   {
       fire_missiles();
   }
}

19
그래서 우리는 일부 피의 바보가 C에서 할당 연산자로 "="를 선택했기 때문에 const가 필요하다고 말하고 있습니까? ;-)
Steve Jessop

37
물론, 가장 현대적인 컴파일러는 조건문에서 할당에 대한 경고와 우리 오류 플래그 오른쪽으로 치료 경고의 모든 회전 : ->
잭 굵은 글꼴

7
이 예제를 너무 힘들게하지 마십시오 : 이것은 일부 개발자가 if (i == 0) 대신 if (0 == i)를 사용하도록 설득하는 것과 동일한 예입니다. 결국 Doug의 코드 패턴은 "if"문 외부에서 사용할 수 있습니다. 중요한 것은 const의 장점 중 하나를 유머러스하게 보여줍니다. + 1.
paercebal

2
일부 컴파일러 (및 보풀)는 오랫동안 이것에 대해 경고 해 왔으며 const : codepad.org/Nnf5JUXV보다이 오타를 잡는 것이 훨씬 더 유용합니다 .

7
@Roger 당신은 우리가 빌드가 깨끗하고 경고가없는 세상에 살고 있다고 가정합니다. 내 경험에 따르면 많은 코드에서 경고음이 사라집니다. 또한 if 표현식에서 대입을 수행하는 많은 코드가 있으며 많은 사람들이 그것이 유효한 "좋은"스타일이라고 주장 할 것입니다.
Doug T.

62

const로 표시 할 때마다 오류가 발생하고 const가되도록 다른 함수를 변경해야합니다. 그런 다음 다른 곳에서 다른 기능을 변경해야합니다. 이것이 경험으로 더 쉬워지는 것입니까?

경험상 이것은 완전한 신화입니다. const-correct가 아닌 것이 const-correct 코드와 함께있을 때 발생합니다. 처음부터 const-correct를 디자인하면 결코 문제가되지 않습니다. const를 만들고 다른 것이 호환되지 않으면 컴파일러가 매우 중요한 것을 말하고 있으므로 올바르게 수정해야합니다 .


7
이것은 내가 데이터를 수정하는 것을 잊었 기 때문에 const가 아닌 함수를 호출하려고하는 const 함수가있는 많은 버그를 예방하는 데 도움이되었습니다.
Mooing Duck

9
깨끗한 코드 기반으로 시작하는 사람은 거의 없습니다. 대부분의 코딩은 레거시 코드를 유지 관리하는 것이며 인용 된 주석은 매우 정확합니다. 나는 새로운 리프 함수를 작성할 때 const를 사용하지만, 십여 개 또는 십여 개의 호출 수준의 낯선 코드를 통해 물건을 쫓을 가치가 있는지 의문을 제기합니다.
Warren Dew

3
이것은 내 경험상 완전히 잘못되었습니다. 내포 된 점 유형은 이런 종류의 문제에 가장 큰 골칫거리를 만들어 단일 유형에 여러 const-quantifier를 가질 수 있습니다.
Noldorin

4
"처음부터 const-correct를 디자인한다면"실제로 처음부터 const-correctness를 강요하는 사치가 몇 번입니까? 우리 대부분은 그렇지 않은 일일 기반에서 수많은 API와 라이브러리를 처리해야하며 이에 대해 할 수있는 일은 거의 없습니다. 그래서 나는 OPs 정서에 동의합니다. "나는 무언가를 const로 표시 할 때마다 오류가 발생하는 것 같습니다"...
nyholku

@WarrenDew 그것은 전이적인 주장입니다. 원저자가 const제대로 사용했다면 (즉, "처음부터") 실제로 문제가되지 않을 것입니다. 정확히 요점입니다!
궤도에서 가벼운 레이스

31

처음 코드를 작성할 때는 그렇지 않습니다. 클래스 또는 인터페이스 내에서 메소드 선언을보고있는 다른 사람 (또는 몇 개월 후에)이 수행하는 작업을 확인하는 것입니다. 객체를 수정하지 않는 것은 그로부터 수집해야 할 중요한 정보입니다.


1
이것은 사실 일뿐입니다. Const는 인터페이스 등을 통해 변수를 적용하기위한 보호 기능으로도 사용됩니다.
Jordan Parmer

그러나 규율이 지정된 코딩 방법과 포스터 상태를 통해이를 시행 할 수 있습니다. 실제 이점은 이것이 API에 반영되어 있기 때문입니다.
안토니오 헤일리

2
바로 그거죠. "const int Value = 5;"를 사용하는 것이 좋습니다. "int ConstValue = 5;"보다 큽니다. +1.
paercebal

6
const-correctness를 적시에 넣는 것은 API를 처음 작성할 때입니다. 그렇지 않으면 개조 할 때 const-poisoning에 어려움을 겪을 수 있습니다 (따라서 오래된 코드에 추가 하는 것이 새로운 코드에서 수행하는 것과 완전히 다른 문제입니다 ).
Donal Fellows

@ DonalFellows는 나중에 const에 넣었다고 말하지 않습니다. const가 이미있는 코드를 읽을 때 나중에 혜택얻는다 는 말입니다
Caleth

27

const를 엄격하게 사용하면 대부분의 함수에 실제 변수가 얼마나 적은지 놀랄 것입니다. 종종 루프 카운터 이상입니다. 코드가 그 지점에 도달하면 내부에서 따뜻한 느낌을 얻습니다 ... 컴파일로 유효성 검사 ... 기능 프로그래밍 영역이 가까이 있습니다 ... 지금 거의 만질 수 있습니다 ...


1
C ++ 17과 constexpr goodness 이후로 컴파일 타임 단위 테스트를 작성하고 있습니다 ... 더 가깝게 가까워지고 있습니다.
QBziZ

22

const는 개발자로 만들고 약속에 컴파일러의 도움을 요청하는 약속입니다.

const-correct 인 나의 이유 :

  • 변수 또는 객체를 변경하지 않을 것이라고 함수의 클라이언트와 통신합니다.
  • const 참조로 인수를 허용하면 값으로 전달하는 안전과 함께 참조로 전달하는 효율성이 제공됩니다.
  • 인터페이스를 const로 작성하면 클라이언트가 인터페이스를 사용할 수 있습니다. const가 아닌 참조를 사용하도록 인터페이스를 작성하는 경우 const를 사용하는 클라이언트는 작업을 위해 constness를 캐스트해야합니다. 인터페이스가 비 const char *를 허용하고 클라이언트가 std :: strings를 사용하는 경우 특히 성가시다. 왜냐하면 const char * 만 가져올 수 있기 때문입니다.
  • const를 사용하면 컴파일러가 정직하게 유지되므로 변경해서는 안되는 것을 실수로 변경하지 않습니다.

20

저의 철학은 컴파일 타임 검사와 함께 nit-picky 언어를 사용한다면 최대한 활용하는 것입니다. const컴파일러가 강제로 의미 하는 바를 전달하는 방법입니다 ... 댓글이나 doxygen 이하는 것보다 낫습니다. 당신은 가격을 지불하고, 왜 가치를 도출하지 않습니까?


20

const없이 C ++를 프로그래밍하는 것은 안전 벨트가없는 상태에서 운전하는 것과 같습니다.

차를 밟을 때마다 안전 벨트를 착용하는 것은 고통스럽고 365 일 중 364 일은 안전하게 도착할 것입니다.

유일한 차이점은 자동차에 문제가 생겼을 때 즉시 느끼게되는 반면 const가없는 프로그래밍에서는 2 주 동안 검색해야 할 수 있습니다. 충돌을 일으킨 원인은 실수로 효율성을 위해 비 const 참조로 전달했습니다.


18

임베디드 프로그래밍의 경우 const 경우 전역 데이터 구조를 선언 할 때 신중하게 하면 부팅시 RAM에 복사하지 않고 상수 데이터를 ROM 또는 플래시에 배치하여 많은 RAM을 절약 할 수 있습니다.

일상적인 프로그래밍에서 const신중하게 사용 하면 문자열 리터럴 및 기타 상수 전역 데이터를 수정하려고 시도하므로 충돌하거나 예기치 않게 동작하는 프로그램을 작성하지 않아도됩니다.

대규모 프로젝트에서 다른 프로그래머와 함께 작업 할 때 const올바르게 사용 하면 다른 프로그래머가 방해하는 것을 방지 할 수 있습니다.


13

const뒤에서 "사물을 바꾸는"코드를 격리하는 데 도움이됩니다. 따라서 클래스에서는 객체의 상태를 변경하지 않는 모든 메소드를로 표시합니다 const. 이는 const해당 클래스의 인스턴스가 더 이상 비 const메소드 를 호출 할 수 없음을 의미합니다 . 이렇게하면 실수로 객체를 변경할 수있는 기능을 호출 할 수 없습니다.

또한 const오버로드 메커니즘의 일부이므로 동일한 시그니처를 사용하지만 두 가지 방법을 사용할 수 있습니다 const. 하나 constconst참조를 요구하고 다른 하나는 비 const참조를 요구합니다.

예:

#include <iostream>

class HelloWorld {
    bool hw_called;

public:
    HelloWorld() : hw_called(false) {}

    void hw() const {
        std::cout << "Hello, world! (const)\n";
        // hw_called = true;  <-- not allowed
    }

    void hw() {
        std::cout << "Hello, world! (non-const)\n";
        hw_called = true;
    }
};

int
main()
{
    HelloWorld hw;
    HelloWorld* phw1(&hw);
    HelloWorld const* phw2(&hw);

    hw.hw();    // calls non-const version
    phw1->hw(); // calls non-const version
    phw2->hw(); // calls const version
    return 0;
}

13

const 정확성은 처음부터 실제로 필요한 것들 중 하나입니다. 아시다시피, 나중에 추가하려는 큰 고통, 특히 추가하려는 새 함수와 이미 존재하는 불확실한 오래된 함수 사이에 많은 의존성이있는 경우.

내가 작성한 많은 코드에서 작곡을 많이 사용하는 경향이 있기 때문에 노력의 가치가 있습니다.

class A { ... }
class B { A m_a; const A& getA() const { return m_a; } };

만약 우리가 const-correctness를 가지고 있지 않다면, 아무도 당신의 등 뒤에서 클래스 B의 내부 상태를 조작하는 사람이 없음을 확신하기 위해 값으로 복잡한 객체를 반환해야합니다.

간단히 말해서 const-correctness는 고통을 덜어주는 방어적인 프로그래밍 메커니즘입니다.


7

파이썬에 변수가 있다고 가정 해보십시오. 당신은 당신이 그것을 수정 해서는 안된다는 것을 알고 있습니다 . 실수로한다면?

C ++을 사용하면 실수로 할 수 없었던 일을 실수로하지 않도록 자신을 보호 할 수 있습니다. 기술적으로 당신은 어쨌든 주위를 돌아 다닐 수 있지만, 당신은 자신을 촬영하기 위해 추가 작업을해야합니다.



3

"const"키워드를 사용하면 클래스에 다른 인터페이스를 지정하게됩니다. 모든 메소드를 포함하는 인터페이스와 const 메소드 만 포함하는 인터페이스가 있습니다. 분명히 이것은 당신이 변경하고 싶지 않은 것들에 대한 액세스를 제한 할 수 있습니다.

예, 시간이 갈수록 쉬워집니다.


2

나는 이론상의 정확성을 좋아합니다 ... 실제로 엄격하게 적용하려고 시도 할 때마다 결국에는 고장이 나고 const_cast는 코드를 못 생기게합니다.

어쩌면 그것은 내가 사용하는 디자인 패턴 일 수도 있지만 const는 항상 브러시가 너무 넓습니다.

예를 들어, 간단한 데이터베이스 엔진을 상상해보십시오. 스키마 객체, 테이블, 필드 등이 있습니다. 사용자는 테이블 스키마 자체를 수정할 수 없다는 'const Table'포인터가있을 수 있습니다. 테이블과 관련된 데이터? Insert () 메서드가 const로 표시되면 내부적으로 실제로 데이터베이스를 조작하기 위해 constness를 캐스팅해야합니다. const로 표시되지 않으면 AddField 메서드를 호출하지 못하도록 보호하지 않습니다.

아마도 답은 constnessness 요구 사항에 따라 클래스를 분할하는 것이지만, 그것이 얻는 이점을 위해 디자인보다 더 복잡하게 만드는 경향이 있습니다.


나는 당신의 예제가 const를 과도하게 사용하는 경우라고 생각하지만 변이를 제거하기 위해 인스턴스 변수에 적용될 수있는 변경 가능한 수정자를 잊지 마십시오.
Zooba

2
Insert () 함수는 이름이 잘못 지정되지 않은 한 언제 const로 표시됩니까? 사물을 추가하면 일반적으로 추가 한 사물이 수정되므로 의미가 없습니다. 실제로 원하는 것은 TableWithConstSchema였습니다.
Greg Rogers

다른 클래스를 추가 할 수는 있지만 const-correctness를 위해 API를 불필요하게 복잡하게 만들고 싶지는 않습니다.
Rob Walker

1

다음 코드에 따라 const와 함께 컴파일러 힌트를 제공 할 수 있습니다 ....

#include <string>

void f(const std::string& s)
{

}
void x( std::string& x)
{
}
void main()
{
    f("blah");
    x("blah");   // won't compile...
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.