문제

종종 나는 an을 추가한다 Empty 내 C ++ 객체에 대한 메소드 다음과 유사한 코드를 사용하여 내부 상태를 지우기 위해.

class Foo
{
private:
    int n_;
    std::string str_;
public:
    Foo() : n_(1234), str_("Hello, world!")
    {
    }

    void Empty()
    {
        *this = Foo();
    }
};

이것은 생성자에서 코드를 복제하는 것보다 낫지 만 *this = Foo() 물체를 청소하고 싶을 때 일반적인 접근법입니까? 뒷면에 나를 물기 위해 기다리는 데 문제가 있습니까? 이런 종류의 일을 달성하는 다른 더 좋은 방법이 있습니까?

도움이 되었습니까?

해결책

생성자가 대신 내 함수를 호출하게했습니다.

class Foo
{
private:
    int n_;
    std::string str_;
public:
    Foo()
    {
        Reset();
    }

    void Reset()
    {
        n_ = 1234;
        str_ = "Hello, world!";
    }
};

예, 당신은 불필요하게 문자열을 빈 문자열로 먼저 초기화 한 다음 과제를 수행하지만 훨씬 더 명확합니다.

다른 팁

잠재적 인 문제? *이것은 정말로 Foo라는 것을 어떻게 알 수 있습니까?

이 빈 방법으로 수행하는 작업은 본질적으로 새로 구성된 개체를 변수 (빈 함수가하는 일)에 수동으로 할당하는 것과 동일합니다.

개인적으로 빈 방법을 제거하고 해당 방법의 모든 용도를 다음과 같이 대체했습니다.

// let's say, that you have variables foo and pfoo - they are properly initialized.
Foo foo, *pfoo;

// replace line "foo.Empty()" with:
foo = Foo();

// replace line "pfoo->Empty()" with:
delete pfoo;
pfoo = new Foo();
// or
*pfoo = Foo();

나는이 빈 방법을 사용하는 데 실제로 이점이 없습니다. 그것은 마녀의 물체에 실제로 일어나는 일을 숨 깁니다. 이름은 최선의 선택도 아닙니다.

발신자가 실제로 깨끗한 객체를 원한다면 - 그는 물체를 직접 구성하는 데 아무런 문제가 없습니다.

또한 불변의 물건을 만드는 것을 고려하십시오. , 건설되면 변경할 수 없습니다. 이것은 많은 시나리오에서 예상치 못한 부작용에서 벗어날 수 있습니다.

당신이 제안한 것보다 더 일반적인 것이 있습니다. 스왑 사용.

기본적으로 당신은 다음과 같은 일을합니다.

T().swap(*this);

많은 표준 컨테이너 (모든 STL 컨테이너?)에는 일정한 시간 스왑 방법이 있으므로 컨테이너를 제거하고 저장 공간이 해제되는지 확인하는 멋진 방법입니다.

마찬가지로 컨테이너를 "수축"하는 좋은 방법이지만 기본 생성자 대신 사본 생성자를 사용하는 좋은 방법입니다.

배치 사용을 고려하십시오 new:

void Empty() {
    this->~Foo();
    new (this) Foo();
}

코드가 호출됩니다 operator = 모든 종류의 부작용으로 이어질 수 있습니다.

편집하다 의견에 응답하여. -이 코드입니다 분명히 잘 정의 된 표준은 명시 적으로 허용합니다. 시간을 찾으면 나중에 단락을 게시 할 것입니다. 에 대한 delete - 물론이야. 내가 의미하는 바는 ~Foo(), 이것은 감독이었습니다. 그리고 네, Rob도 옳습니다. 문자열의 파괴자를 호출하기 위해서는 실제로 물체를 파괴해야합니다.

생성자에 동적으로 할당 된 메모리가있는 경우 이것은 메모리 누출의 잠재적 소스가 될 수 있습니다.

내가하는 방법은 다음과 같습니다.

class Foo {
private:
    int n_;
    std::string str_;
public:
    Foo() : n_(1234), str_("Hello, world!")
    {
    }

    void Empty()
    {
        Foo f;
        swap(f);
    }

    void swap(Foo & other) {
        std::swap(n_, other.n_);
        swap(str_, other.str_);
    }
};

void swap(Foo & one, Foo & other) {
    one.swap(other);
}

스왑 함수를 FOO 클래스와 동일한 네임 스페이스에 넣으십시오. 인수 의존적 조회는 사용자가 2 개의 foo를 교환하기 위해 교환하기 위해 호출 할 때이를 찾습니다. 당신은 구현할 수 있습니다 operator= 스왑 기능도 사용합니다.

이것은 생성자에서 코드를 복제하는 것보다 낫지 만 *this = foo ()가 객체를 지우고 싶을 때 일반적인 접근법인지 궁금했습니다.

물체를 지우는 것은 일반적인 일이 아닙니다. 더 일반적으로, 객체 (아마도 불변의 물체조차도)가 인스턴스화되고 실제 데이터를 포함하거나 인스턴스화되지 않습니다.

가장 일반적인 종류 ~이다 재설정은 컨테이너가 될 것입니다 ...하지만 지금은 자신의 컨테이너 클래스를 작성하지 않을 것입니다.

뒷면에 나를 물기 위해 기다리는 데 문제가 있습니까?

예:

  • 이것이 실제로는 아니었다면 Foo 그러나 대신 a DerivedFoo
  • 만약에 Foo의 과제 연산자가 존재하지 않거나 버그가없는 경우 (예 : 정의되지 않았고 기본 연산자가 양호하지 않은 경우, 예 : 데이터 구성원이 알몸 포인터입니다).

이런 종류의 일을 달성하는 다른 더 좋은 방법이 있습니까?

예, 자유 기능이 더 나을 수도 있습니다 (위의 문제를 모두 피할 수 있습니다) :

template<class T> void reconstruct(T* p)
{
    p->~T();
    new (p) T();
}

예, 이것은 성능 측면에서 효율적이지 않으며 (제자리에 작동하는 대신 다른 FOO 객체를 만드는) 불쾌한 메모리 누출로 생성자에 메모리를 할당하면 물게됩니다.

메모리 측면에서 더 안전하게 만드는 것은 this-> 삭제를 호출하면 this = new foo () - 느리게됩니다.

초고속이 되려면 정적 빈 객체 필드를 만들어 재설정 중입니다.

속성을 빠르게 할당하려면 속성을 하나씩 할당하십시오.

ATES Goral이 제안한대로 CTOR의 복제 호출을 재설정하지 않고 합리적인 스타일을 유지하려면 기본 매개 변수로 더 빠른 구조를 잃게됩니다.

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