2008-09-19 10 views
12

이 함수는 객체의 상태를 변경할 수 없다는 것을 이해하지만 컴파일러가 동일한 인수로 함수를 호출하면 동일한 값을 반환하므로 캐시 된 값을 사용할 수있는 경우 다시 사용할 수 있습니다. 예 : const 멤버 함수의 의미는 무엇입니까?

class object 
{ 
    int get_value(int n) const 
    { 
     ... 
    } 

... 


object x; 

int a = x.get_value(1); 
    ... 
int b = x.get_value(1); 

다음 컴파일러는 멀리 두 번째 전화를 최적화하고 두 레지스터의 값을 사용하거나 단순히 b = a;

이 사실인가요 할 수 있을까?

답변

22

const은 구현 세부 정보가 아니라 프로그램 의미에 관한 것입니다. 개체의 표시 상태가 변경되지 않을 때 멤버 함수 const을 표시해야하며 자체 개체 인 const에서 호출 가능해야합니다. 클래스 X에있는 const 멤버 함수 내에서 this의 유형은 X 개체에 대한 포인터 인 X const *입니다. 따라서 모든 멤버 변수는 해당 멤버 함수 내에서 const입니다 (mutable 멤버 제외). const 개체가있는 경우에는 const 회원 기능 만 호출 할 수 있습니다.

mutable을 사용하면 멤버 변수가 const 멤버 함수 내에서 변경 될 수 있음을 나타낼 수 있습니다. 이것은 일반적으로 결과 캐싱에 사용되는 변수를 식별하거나 mutexes와 같이 실제 관찰 가능한 상태에 영향을주지 않는 변수 (즉, const 멤버 함수에서 뮤텍스를 잠글 필요가 있음)를 사용하거나 카운터를 사용하는 데 사용됩니다.

class X 
{ 
    int data; 
    mutable boost::mutex m; 
public: 
    void set_data(int i) 
    { 
     boost::lock_guard<boost::mutex> lk(m); 
     data=i; 
    } 
    int get_data() const // we want to be able to get the data on a const object 
    { 
     boost::lock_guard<boost::mutex> lk(m); // this requires m to be non-const 
     return data; 
    } 
}; 

당신은 그 포인터가 const 멤버 함수에 const이된다 (예 : std::auto_ptr 또는 boost::shared_ptr 같은 스마트 포인터 포함),하지만 -을 지적 데이터를 수정할 수 없습니다 때문에 직접 포인터보다는하여 데이터를 보유하는 경우 포인트 된 데이터

캐싱과 관련 : 일반적으로 컴파일러는 상태가 호출간에 변경 될 수 있으므로 (특히 뮤텍스가있는 다중 스레드 예제에서) 컴파일러가이를 수행 할 수 없습니다. 그러나 정의가 인라인이라면 컴파일러는 코드를 호출 함수로 끌어 올 수 있고 거기에서 볼 수있는 것을 최적화 할 수 있습니다. 이로 인해 함수가 실제로 만 호출 될 수 있습니다.

C++ Standard (C++0x) 다음 버전의 새 키워드는 constexpr입니다. constexpr 태그가 지정된 함수는 상수 값을 반환하므로 결과를 캐시 할 수 있습니다. 컴파일러가이 사실을 확인할 수 있도록하기 위해서 당신이 할 수있는 일에는 한계가있다.

+0

아! constexpr 아마 내가 생각하고 있었어! 감사. – Ferruccio

+0

당신은 내 하루를 보냈습니다. 나는 항상 필요한 것은 모두 '변경 가능하다'라는 것을 몰랐다. 고맙습니다. – lucastamoios

0

나는 의심 스럽지만 함수는 여전히 세계의 상태를 변경하고 const를 위반하지 않는 전역 함수를 호출 할 수 있습니다.

2

구성원 함수의 const 키워드는 매개 변수를 상수로 표시합니다. 이 함수는 전역 데이터를 여전히 음소거 할 수 있으므로 (캐싱 할 수는 없지만) 개체 데이터는 사용할 수 없습니다 (const 개체에 대한 호출을 허용 함).

+0

: - 예를 들어, 다음은 완벽하게 합법적 (안 캐시 0 반복 호출) (바 증가 값을 반환합니다)입니다 그것. 이것은 주로 마지막 결과 캐싱에 유용합니다. :-) – 0124816

2

여기서, const 멤버 함수는 thisconst 포인터로도 취급된다는 것을 의미합니다. 실제로는 const 멤버 함수 내에서 this의 상태를 수정할 수 없다는 의미입니다. 노 부작용 함수의

(즉, 당신이 달성하기 위해 노력하고), GCC는 pure라는 "기능 속성"(당신이 __attribute__((pure)) 말하여 사용)이 있습니다 http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

+0

나는 부작용을 일으키려고하지 않고있다. 함수를 const로 만드는 모든 의미를 이해하고 싶습니다. – Ferruccio

3

번호

const 메서드는 개체 (즉 해당 필드)의 상태를 변경하지 않는 메서드이지만 동일한 입력을 받으면 const 메서드의 반환 값이 결정됩니다. 즉, const 키워드는 해당 기능이 일대일임을 의미하지 않습니다. 예를 들어 현재 시간을 반환하는 메서드는 const 메서드이지만 해당 반환 값은 호출간에 변경됩니다.

0

멤버 함수가 전역 데이터를 수정할 수 있다는 사실 외에도 멤버 함수는 해당 개체의 명시 적으로 선언 된 변경 가능한 멤버를 수정할 수 있습니다.

2

멤버 변수에 대한 키워드 mutable을 사용하면 const 함수가 현재 사용중인 개체의 상태를 변경할 수 있습니다. 하지만, 포인터를 const가 될 수

int something() const { return m_pSomeObject->NextValue(); } 

하는 것으로 다음 코드 이후

그리고 아니, 그렇지 않은 캐시 데이터 (적어도 모든 호출) 시간이 지남에 따라 변화 유효한 CONST 기능입니다 가리키는 객체가 const가 아니기 때문에 SomeObject에서 NextValue를 호출하면 자체 내부 상태가 변경되거나 변경되지 않을 수 있습니다. 이로 인해 함수가 호출 될 때마다 다른 값을 반환합니다.

그러나 컴파일러가 const 메서드로 어떻게 작동하는지 나는 대답 할 수 없습니다. 나는 특정 일을 최적화 할 수 있다고 들었지만 확실하게 살펴 봐야 할 것입니다.

0

코리 정확하지만 명심 그 const 멤버 함수에 수정 변경할 수 로 표시된 임의의 멤버 변수.

또한 이러한 함수가 다른 const 함수 또는 다른 const 참조를 통해 호출 될 수 있음을 의미합니다.


편집 : 젠장, 9 초에 맞았다 .... 9 !!! :)

+0

서부에서 가장 빠른 총, 많이? :-P –

+0

안녕하세요, 제 답변이 당신보다 9 초 앞서있었습니다. : P – KTC

0

const 메소드는 정적 로컬을 수정할 수도 있습니다. 당신은 회원이 다음 CONST 기능은 여전히 ​​가변 수정할 수 있습니다라고 표시된 경우, 실제로

class Foo 
{ 
public: 
    int bar() const 
    { 
     static int x = 0; 
     return x++; 
    } 
}; 
관련 문제