문제

다음과 같은 무료 함수가 있다고 가정해 보겠습니다. InitFoo.이 함수가 우연히 여러 번 호출되는 것을 방지하고 싶습니다.별 생각 없이 다음과 같이 썼습니다.

void InitFoo()
{
    {
        static bool flag = false;
        if(flag) return;
        flag = true;
    }

    //Actual code goes here.
}

하지만 이것은 큰 사마귀처럼 보입니다. InitFoo 하다 ~ 아니다 다른 상태 정보를 보존해야 합니다.누군가 추악함 없이 동일한 목표를 달성할 수 있는 방법을 제안할 수 있습니까?

물론 매크로는 중요하지 않습니다.

도움이 되었습니까?

해결책

당신은 다른 추함을 가지고 그것을 할 수 있습니다:

struct InitFoo
{
     InitFoo()
     {
         // one-time code goes here
     }
};

void Foo()
{
    static InitFoo i;
}

아직도 사용 중이시군요 static, 하지만 이제는 플래그 확인을 직접 수행할 필요가 없습니다. static 이미 플래그와 그에 대한 검사를 넣었으므로 단지 구성만 합니다. i 한 번.

다른 팁

글쎄, 생성자는 자동으로 한 번만 호출됩니다. 이 클래스의 단일 인스턴스를 만드는 경우 :

class Foo
{
public:
    Foo(void)
    {
        // do stuff
    }
}

그 다음에 //do stuff 한 번만 실행됩니다. 두 번 실행하는 유일한 방법은 클래스의 다른 인스턴스를 만드는 것입니다.

a를 사용하여이를 방지 할 수 있습니다 하나씩 일어나는 것. 사실상, //do stuff 한 번만 호출 될 수 있습니다.

이 기능을 우연히 여러 번 호출하지 않도록 보호하고 싶습니다.

나에게 이것은 디버깅 중에 만 나오는 문제처럼 들린다. 이 경우, 나는 단순히 다음을 수행 할 것입니다.

void InitFoo()
{
    #ifndef NDEBUG
       static bool onlyCalledOnce = TRUE;
       assert(onlyCalledOnce);
       onlyCalledOnce = FALSE;
    #endif

    ...
}

이 특정 사마귀의 목적은 단지 그것을 보면 쉽게 식별되며, 프로그래머가 전화의 실수를 저지르면 멋지고 크고 화려한 주장 실패를 일으킬 것입니다. InitFoo 두 번 이상. 또한 생산 코드에서 완전히 분리 될 것입니다. (언제 NDEBUG 정의됩니다).

편집하다: 동기 부여에 대한 빠른 메모 :
init 함수를 두 번 이상 호출하는 것은 아마도 큰 오류 일 것입니다. 이 기능의 최종 사용자가 실수로 두 번 불렀다면 조용히 그 실수를 무시하는 것은 아마도 갈 길이 아닐 것입니다. 당신이 가지 않는다면 assert() 경로, 나는 적어도 메시지를 덤프하는 것이 좋습니다. stdout 또는 stderr.

그것이 바로 내가하는 방식입니다. 대안을 원한다면 기능 포인터 셔플 링을 사용할 수 있습니다.

static void InitFoo_impl()
{
    // Do stuff.

    // Next time InitFoo is called, call abort() instead.
    InitFoo = &abort;
}

void (*InitFoo)() = &InitFoo_impl;

멀티 스레드 금고가 필요합니까? 이중 점검 잠금 장치로 싱글 톤 패턴을 살펴보십시오 (잘못되기 쉽습니다).

이를 위해 전체 수업을 원하지 않는다면 또 다른 간단한 방법은 다음과 같습니다.

.cpp에서 (.h에서 initblah를 선언하지 마십시오)

 // don't call this -- called by blahInited initialization
static bool InitBlah() 
{
   // init stuff here
   return true;
}
bool blahInited = InitBlah();

아무도이 .CPP 외부에서 호출 할 수 없으며 호출됩니다. 물론, 누군가 가이 .CPP에서 그것을 부를 수 있습니다.

주문에 관심이 있거나 특정 시간에 수행하는 경우 싱글 톤이 아마도 당신을위한 것입니다.

나는 일회성 전용이지만 가치가 없지만 냉담한 등급이 필요한 상황에서 항상 그렇게합니다. 물론 스레드 관련 문제에 대해 걱정하지 않는다고 가정합니다. 나는 일반적으로 변수 이름을 "s_"로 접두사로 정적 변수임을 분명히합니다.

흠 ... 사용에 반대하지 않는다면 후원, 그런 다음 살펴보십시오 부스트 :: call_once:

namespace { boost::once_flag foo_init_flag = BOOST_ONCE_INIT; }

void InitFoo() {
    // do stuff here
}

void FooCaller() {
    boost::call_once(&foo_init_flag, InitFoo);
    // InitFoo has been called exactly once!
}

void AnotherFooCaller() {
    boost::call_once(&foo_init_flag, InitFoo);
    // InitFoo has been called exactly once!
}

나는 그것에 대해 매우 흥분하지는 않지만 이것은 또 다른 방법입니다 : 함수 객체.

#import <iostream>

class CallOnce {
private:
    bool called;
public:
    CallOnce() {
        called = false;
    }
    void operator()(void) {
        if (called) {
            std::cout << "too many times, pal" <<std::endl;
            return;
        }
        std::cout << "I was called!" << std::endl;
        called = true;
    }

};

int main(void) {
    CallOnce call;

    call();
    call();
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top