[c] 순수 기능의 이점

오늘 나는 순수한 기능에 대해 읽고 그 사용법과 혼동했습니다.

동일한 입력 세트에 대해 동일한 값 세트를 반환하고 관찰 가능한 부작용이없는 함수는 순수하다고합니다.

예를 들어 strlen()는 순수한 기능 rand()이고은 불순한 기능 입니다.

__attribute__ ((pure)) int fun(int i)
{
    return i*i;
}

int main()
{
    int i=10;
    printf("%d",fun(i));//outputs 100
    return 0;
}

http://ideone.com/33XJU

위의 프로그램은 pure선언 이 없을 때와 같은 방식으로 작동합니다 .

함수를 pure[출력에 변화가없는 경우] 로 선언하면 어떤 이점이 있습니까?



답변

pure 컴파일러에게 함수에 대한 특정 최적화를 수행 할 수 있음을 알려줍니다. 다음과 같은 코드를 상상해보십시오.

for (int i = 0; i < 1000; i++)
{
    printf("%d", fun(10));
}

순수 함수를 사용하면 컴파일러는 fun(10)1000 번이 아니라 한 번만 평가해야한다는 것을 알 수 있습니다 . 복잡한 기능의 경우 큰 승리입니다.


답변

함수가 ‘순수하다’고 말하면 외부에서 눈에 보이는 부작용이 없음을 보장하는 것입니다 (댓글에서 말했듯이 거짓말을하면 나쁜 일이 발생할 수 있음). 함수가 ‘순수’라는 것을 알면 컴파일러에 이점이 있으며이 지식을 사용하여 특정 최적화를 수행 할 수 있습니다.

다음은 GCC 문서 에서 pure속성 에 대해 말하는 내용입니다 .

순수한

반환 값을 제외하고 많은 함수는 효과가 없으며 반환 값은 매개 변수 및 / 또는 전역 변수에만 의존합니다. 이러한 함수는 산술 연산자처럼 공통 하위 표현식 제거 및 루프 최적화의 대상이 될 수 있습니다. 이러한 함수는 pure 속성으로 선언해야합니다. 예를 들면

          int square (int) __attribute__ ((pure));

Philip의 대답은 이미 함수가 ‘순수’라는 것을 아는 것이 루프 최적화에 어떻게 도움이 될 수 있는지 보여줍니다.

다음은 일반적인 하위 표현식 제거를위한 것입니다 (주어진 foo것은 순수함).

a = foo (99) * x + y;
b = foo (99) * x + z;

다음이 될 수 있습니다.

_tmp = foo (99) * x;
a = _tmp + y;
b = _tmp + z;


답변

가능한 런타임 이점 외에도 순수 함수는 코드를 읽을 때 추론하기가 훨씬 쉽습니다. 또한 반환 값이 매개 변수의 값에만 의존한다는 것을 알고 있기 때문에 순수 함수를 테스트하는 것이 훨씬 쉽습니다.


답변

순수하지 않은 기능

int foo(int x, int y) // possible side-effects

순수한 기능의 확장과 같습니다.

int bar(int x, int y) // guaranteed no side-effects

여기에서 명시적인 함수 인수 x, y 외에 우주의 나머지 부분 (또는 컴퓨터가 통신 할 수있는 모든 것)을 암시 적 잠재적 입력으로 가지고 있습니다. 마찬가지로 명시 적 정수 반환 값 외에 컴퓨터에서 쓸 수있는 모든 항목은 암시 적으로 반환 값의 일부입니다.

순수하지 않은 함수보다 순수 함수에 대해 추론하는 것이 왜 훨씬 더 쉬운 지 분명해야합니다.


답변

애드온과 마찬가지로 C ++ 11이 constexpr 키워드를 사용하여 내용을 코드화한다는 점을 언급하고 싶습니다. 예:

#include <iostream>
#include <cstring>

constexpr unsigned static_strlen(const char * str, unsigned offset = 0) {
        return (*str == '\0') ? offset : static_strlen(str + 1, offset + 1);
}

constexpr const char * str = "asdfjkl;";

constexpr unsigned len = static_strlen(str); //MUST be evaluated at compile time
//so, for example, this: int arr[len]; is legal, as len is a constant.

int main() {
    std::cout << len << std::endl << std::strlen(str) << std::endl;
    return 0;
}

constexpr 사용에 대한 제한으로 인해 함수가 순수함을 입증 할 수 있습니다. 이렇게하면 컴파일러가보다 적극적으로 최적화하고 (꼬리 재귀를 사용하는지 확인하십시오!) 런타임 대신 컴파일 타임에 함수를 평가할 수 있습니다.

따라서 귀하의 질문에 대답하려면 C ++를 사용하는 경우 (C라고 말했지만 관련이 있음) 올바른 스타일로 순수한 함수를 작성하면 컴파일러가 함수로 모든 종류의 멋진 일을 할 수 있습니다. -)


답변

일반적으로 Pure 함수는 컴파일러가 활용할 수있는 불순한 함수보다 3 가지 장점이 있습니다.

캐싱

f100000 번 호출되는 순수 함수가 있다고 가정 해 보겠습니다. 결정적이며 매개 변수에만 의존하기 때문에 컴파일러는 값을 한 번 계산하고 필요할 때 사용할 수 있습니다.

병행

순수 함수는 공유 메모리를 읽거나 쓰지 않으므로 예기치 않은 결과없이 별도의 스레드에서 실행할 수 있습니다.

참조로 전달

함수 f(struct t)t값 으로 인수 를 가져오고 반면에 컴파일러는 값이 변경되지 않고 성능 향상 을 보장하면서 순수로 선언 된 경우 t참조로 전달할 수 있습니다.ft


컴파일 시간 고려 사항 외에도 순수 함수는 매우 쉽게 테스트 할 수 있습니다. 호출하기 만하면됩니다.

개체를 구성하거나 DB / 파일 시스템에 대한 모의 연결을 만들 필요가 없습니다.


답변