2013-09-03 1 views
5

내가 아는 한 C++에서 struct/class 멤버는 동일한 액세스 제어를 사용하여 선언 순서로 메모리에 저장됩니다. 이 예에서mutable member는 변경 불가능한 멤버에 대한 const 최적화를 비활성화합니까?

#include <cstdlib> 
#include <iostream> 

struct X 
{ 
    mutable int m; 
    int   c; 
}; 

const X cx = {0, 1}; 

int main() 
{ 
    X& x = const_cast<X&>(cx); 

    x.m = rand(); 
    x.c = rand(); 

    std::cout<<x.m<<" "<<x.c; 
} 

프로그램 실행 및 인쇄이 개 임의의 숫자 : 다음 예제 mc은 다른 후 하나를 보관해야한다. mutable을 제거하면 cx이 읽기 ​​전용으로 보호 된 메모리에 저장되어 있기 때문에 충돌합니다. 하나 개 mutable 회원은 전체 struct (어떻게 든 모든 회원 mutable을)에 대한 const 최적화를 사용하지 않습니다 -

이 나를 궁금해했다?

struct의 일부는 읽기 전용 메모리에 저장하고 다른 부분은 읽기 전용이 아닌 메모리에 저장할 수 있으며 C++ 표준 메모리 레이아웃을 존중합니까?

Windows 7의 Visual Studio 2010과 Ubuntu의 GCC 4.7.2를 사용하여 테스트되었습니다.

답변

4

struct을 저장할 위치에서 컴파일러가 "모두 또는 아무것도하지 말아야"하는 이유를 설명합니다. 대부분의 프로세서에서 메모리 페이지는 4KB (몇 개는 8KB 페이지)입니다. 이는 "읽기 전용"vs "읽기/쓰기"메모리 블록의 세분성입니다. 따라서 읽기 전용 메모리에 4 바이트 정수를 넣을 수는 없으며 (정확히 4KB 메모리 경계를 넘지 않는 한) 읽기/쓰기 메모리의 다음 4 바이트 정수를 가질 수는 없지만 확실히 낭비적인 용도로 사용하게됩니다. 메모리가 3000 개이면 12MB를 차지합니다.)

"최적화"가 아니라는 점에 유의하십시오. 읽기 전용 메모리는 읽기 - 쓰기 메모리보다 빠르지 않습니다. 이는 사용자가 const으로 바보가되어서 쓰지 말아야하는 데이터에 대한 보호입니다.

struct에 "무언가를 수행하는"생성자를 추가하면 컴파일러가 읽기 전용 켜기/끄기 전환 코드를 생성하는 것이 매우 까다로울 수 있으므로 구조체를 읽기/쓰기 메모리에 저장할 가능성이 높습니다 런타임에.

+0

m (와)과 c (와)과 inx가 이전과 같이 readonly 메모리 내에없는 X() 생성자를 추가했습니다. 매우 흥미로운 통찰력, 감사합니다! – Felics

1

키워드 "const"는 컴파일러 지시문이나 컴파일러 힌트가 아닌 "private"및 "public"과 같은 프로그래머 팀의 레이블입니다. 컴파일러는 최적화를 위해 사용할 수 있지만 그렇게 할 필요는 없습니다. 컴파일러는 악용을 통제하고 방지합니다. 그래서 당신이 보는 행동은 완전히 괜찮습니다. 그리고 하나의 struct 인스턴스 또는 클래스 인스턴스의 일부가 다른 메모리 영역에 존재한다는 것은 불가능합니다 (매핑을 계산하지 않음). 그 결정은 구조체의 사용에 영향을 미치고 프로그래머가 허용해야하기 때문입니다.

+0

"키워드"const "는 프로그래머 팀의 레이블입니다."-이 경우 팀의 구성원이이 레이블의 의미에 대해 약간 다른 견해를 가질 수 있습니다. – SChepurin

+0

좋은 설명은 다음과 같습니다. "const 한정자는 컴파일러가 해당 객체를 직접 수정하려고 시도하는 코드를 거부하는 명령이며, 객체를 간접적으로 수정하려고 시도하면 결과가 정의되지 않은 동작이 발생합니다 . " (http://stackoverflow.com/questions/4275504/deep-analysis-of-const-qualifier-in-c) – SChepurin

+0

당신 말이 맞아요. 내 대답은 서두름으로 작성되었습니다. 그럼에도 불구하고 그것은 내 의견으로는 더 인간이 읽을 수있다. 그리고 여러 해에 걸쳐 여러 팀에서 일하는 예, 저는 사람들이 컴파일러를 속이려고 시도하는 것을 항상 놀라며, 적절한 방식으로이를 수행 할 것으로 기대합니다. –

5

표준은 많은 곳에서 mutable 회원에 대해 말하고 있습니다. 표준의 세 부분 아래에서 const 개체의 mutable 구성원 만 수정할 수 있다고 설명합니다. 그렇지 않으면 입니다. 정의되지 않은 동작입니다.

3.9.3 CV-한정자 [basic.type.qualifier]

CONST 객체const T 또는 객체의 하위 객체 비 변경할 목적으로한다.

[...]

7.1.1 스토리지 클래스 지정자 [dcl.stc]

클래스의 데이터 멤버에 mutable 지정자를 포함하는 클래스의 객체에 적용 CONST 지정자를 무효화 나머지 개체가 const인데도 mutable 클래스 구성원을 수정할 수 있습니다.

[...]

7.1.6.1 이력서-한정자 [dcl.type.cv 임의 반원 선언 이외에는

mutable (7.1.1)가 변형 될 수있다 , 수명 (0.003) 동안 const 오브젝트를 수정하려고 시도하면 이 정의되지 않은 동작이됩니다.


그것은 비 - 읽기 전용 메모리 및 대한 C++ 표준 메모리 레이아웃에 판독 전용 메모리와 다른 부분에 struct 부분을 저장할 수 있는가?

없음, 상기 객체의 나머지 부분과는 다른 메모리 영역에 struct (또는 class)의 일부를 저장하는 것은 불가능하다.

+0

그래서'main.c'의'x.c = rand();가 두 경우 모두 UB를 트리거합니다. 맞습니까? – Hulk

+0

@Hulk 예,'m'의'mutable' 키워드는'c'를 위해 아무 것도 바뀌지 않습니다. 이 게시물을보십시오 : http://stackoverflow.com/a/583150/1394283. 제가 인용 한 표준의 마지막 부분을 잘 설명합니다. –

관련 문제