2013-09-16 7 views
2

는 다음 (조금 생각) 예를 고려 아무런 부작용이없는 등의 기능을 표시 :는 비주얼 C++

// a.cpp 
int mystrlen(const char* a) { 
    int l = 0; 
    while (a[l]) ++l; 
    return l; 
} 

// b.cpp 
extern int mystrlen(const char*); 
int foo(const char* text) { 
    return mystrlen(text) + mystrlen(text); 
} 

mystrlen()가없는 컴파일러를 말할 수있는 것은 아주 좋은 것 부작용이 없으므로 두 번 호출하는 대신 mystrlen(text)의 이전 결과를 다시 사용할 수 있습니다.

나는 그것에 관한 문서에서 아무것도 찾지 못했고 restrict이거나 그 차이 중 하나가 그 일을하지 않는 것 같습니다. 모든 최적화가있는 출력 코드 (스위치 /Ox)를 보면 컴파일러가 실제로 두 가지 호출을 생성한다는 것을 알 수 있습니다. 하나의 모듈에 두 기능을 모두 넣어도 마찬가지입니다.

어떤 해결책이든지 VC++에서 해결책이 없다는 것을 누구든지 확인할 수 있습니까?

+0

더 기능적인 언어가 필요합니다. – SLaks

+0

최적화를 모두 켰을 때도 (두 번 호출) 그렇게합니까? 그리고 만약 그것이 같은 소스 파일에 있다면? 여전히 같은 결과? – Floris

+0

@Floris :'/ Ox'을 사용했는데 하나의 모듈에서 함수를 두 번 인라인합니다. – cxxl

답변

-1

C++은 기능적 언어가 아닌 필수 언어이므로 달성하려는 것은 불가능합니다.

당신이 기대하는 동작은 컴파일러에게 C++로 말할 수있는 방법이 아닌 참조 투명성입니다 (그러나 Haskell과 같은 순전히 함수형 프로그래밍 언어에서는 함축적입니다) .

미래의 C++ 표준은 '순수한'또는 '부작용이없는'것으로 기능을 표시 할 수있는 키워드를 소개합니다.

+2

나는 명령형 대 기능성이 플래그를 지정할 수있는 것과 아무런 관련이없는 이유를 알지 못합니다. 특정 기능은 부작용이없는 것으로 (즉, 다른 객체에 대한 결과). 의심의 여지없이, 그것은 C++로 구현 될 수 있습니다. 질문은, 그것입니까? – cxxl

0

찾고 계신 것이 도움이되지 않습니다.

일반적으로 함수가 부작용이 없다고 생각하는 경우에도 컴파일러는 호출을 제거 할 수 없습니다. 그 포인터는 어디서 났니? 신호 처리기가 동일한 포인터에 액세스 할 수 있습니까? 다른 스레드일까요? 컴파일러는 포인터가 가리키는 메모리가 그 아래에서 바뀌지 않을 것이라고 어떻게 알 수 있습니까?

컴파일러는 포인터를 통해 가져온 것들에 대해서도 함수 본문 내에서 중복 페치를 자주 제거합니다. 그러나 이것들이 어느 정도 할 수 있거나 할 수있는 지에는 한계가 있습니다.

여기서 두 함수 호출간에 일관된 내용을 어디에 유지할 것인지 알 수있는 베어 포인터 (bare pointer)를 컴파일러에 알려달라고 요청할 것입니다. 그것은 많은 가정입니다. 물론 포인터를 휘발성이라고 선언하지는 않았지만 여전히 많은 가정을하고 있습니다.

이제 스택에 버퍼를 두 번 연속해서 그 함수에 전달하면 컴파일러는 포인터를 다른 곳으로 전달하지 않은 경우 해당 버퍼의 내용을 안전하게 가정 할 수 있습니다 예기치 않은 시간에 프로그램에서 임의의 다른 것으로 변경되지 않을 것입니다. 를 선언 할 수있는 방법이 있다면 컴파일러가 snprintf이 라이브러리 기능이 있다는 주어진 number했던 일에 대해 만들 수

// b.cpp 
extern int mystrlen(const char*); 
int foo(int bar) { 
    char number[20]; 
    snsprintf(number, 20, "%d", bar); 
    return mystrlen(number) + mystrlen(number); 
} 

을 감안할 때 가정이, 그 다음 mystrlen에 두 번째 호출을 생략하다 수 있습니다 : 예를 들어

mystrlen에는 부작용이 없습니다.