2014-07-26 2 views
5

구조체를 다른 함수에 전달하는 메시지 시스템이 있습니다. 응축 된 예에서, 메시지는 다음과 같이 설명된다 :const 선언 된 객체에서 mutable을 정의되지 않은 동작으로 수정하고 있습니까?

struct Message { 
    bool wasHandled; 

    Message() { 
     wasHandled = false; 
    } 
}; 

및 메시지 핸들러 같이 호출된다

handleMessage(Message()); 

메시지 CONST 참조로 전달된다. 그것에 대한 나의 주된 동기는 위에 한 줄짜리 문장을 쓸 수 있다는 것입니다. const가 아닌 참조를 전달하면 다음과 같이 작성해야합니다.

Message message; 
handleMessage(message); 

핸들 플래그는 메시지가 함수에 의해 처리되었는지 여부를 나타냅니다. 따라서 handleMessage 함수는 wasHandled 플래그를 수정해야합니다. 한 가지 가능한 구현은 다음과 같습니다

void handleMessage(const Message& message) { 
    const_cast<bool&>(message.wasHandled) = true; 
    // Do stuff here. 
} 

하지만, 내 이해에 따르면,

handleMessage(Message()); 

은 동일하다에 :

const Message message; 
handleMessage(message); 
: ( 참고이 잘못된, 허용 대답 참조)

따라서 const 객체의 값을 변경하려고합니다. 그것은 정의되지 않은 동작입니다.

이 동작을 정의 할

struct Message { 
    mutable bool wasHandled; 

    Message() { 
     wasHandled = false; 
    } 
}; 

로 메시지를 선언 할 것인가? 물론 이것은 const 캐스트를 제거합니다.

이 특정 예제에서는 wasHandle 플래그가 실제로 읽히지 않으며 호출자가이를 알기를 원한다면 한 줄자는 사용할 수 없습니다. 그러나 실제로 모든 발신자가 깃발에 관심이있는 것은 아닙니다. 이 메시지는 플래그를 사용하는 handleMessage 안에있는 다른 함수로 전달 될 수도 있습니다.

+0

@juanchopanza :

당신이 정말로 (즉, 다른 설계 문제의 증상 여부와는 논쟁의 여지가있어) 모두 변경 가능 lvalues과 우변을 처리하려면

, 당신은 단순히 두 기능 과부하가 있어야합니다 어떻게 그 문제를 피할 수 있겠습니까? handleMessage 함수는 여전히 플래그를 수정해야합니다. 그리고 AFAIK 생성자는 const 선언 된 객체에서도 구성원을 수정할 수 있습니다. – rasmus

+4

mutable로하는 일은 정의되지 않은 동작이 아닙니다. 그것이 변경 될 수있는 전체 지점입니다. –

+0

죄송합니다, 나는 잠 들어 있습니다. 예, 괜찮습니다. 그것은'mutable '을위한 것입니다. – juanchopanza

답변

4

지나치게 복잡합니다. 우선, 임시 객체에 대한 이해가 잘못되었습니다. Message()은 완벽하게 변경할 수있는 값입니다. 그것은 단지 rvalue 인 이유로 lvalue reference에 바인딩 할 수 없다는 것입니다.

void handleMessage(Message & m) { handleImpl(m); } 
void handleMessage(Message && m) { handleMessage(m); } 
+0

handleImpl는 필요하지 않습니다. rvalue ref 오버로드는 lvalue ref 1에 자유롭게 위임 할 수 있습니다. – Puppy

+0

@Puppy : 사실, 좋은 지적입니다. –

+0

감사합니다. 이 맥락에서 rvalue 참조를 잊어 버렸습니다. 나는 골동품이다 : pre C++ 11은 어떨까요? rvalue 참조가 존재하지 않으므로 임시 변수는 여전히 변경 가능합니까? – rasmus