2014-11-12 5 views
0

내가 가지고있는 다음과 같은 두 개의 클래스 : 나는 정수에 대한 참조로 두 번째의 필드 ref는 :: 변형을 높이고, 함께 참조 필드 유형

struct A { 

    A() : state(0) { } 
    A(int state_arg) 
     : state{ state_arg } { } 

    int state; 
}; 

struct B { 

    B(int state_arg, const int& ref) 
     : state{ state_arg }, ref{ ref } { } 

    int state; 
    const int& ref; 
}; 

다른 위치에서 B의 일부 인스턴스 state 필드 (아마도 필요하지는 않음).

이제 이러한 유형에 대해 몇 가지 작업을 수행하려고합니다. 실제로 boost :: variant 라이브러리를 사용합니다.

using my_type = boost::variant<A, B>; 

이제 my_type의 변수를 사용할 때 모두 예상대로 작동합니다. 예를 들면 :

int main() { 

    my_type a(A(45)); 
    my_type b(B(45, boost::get<A>(a).state)); 

    A& at = boost::get<A>(a); 
    B& bt = boost::get<B>(b); 

    if (at.state == bt.ref) { 
     std::cout << "AS EXPECTED" << std::endl; 
    } 
    // that prints "AS EXPECTED" 
} 

하지만이 std::vectormy_type의 작업을 할 때 일이 잘못!

int main() { 

    std::vector<my_type> vec; 
    vec.push_back(A(45)); 
    vec.push_back(B(45, boost::get<A>(vec[0]).state)); 

    A& at = boost::get<A>(vec[0]); 
    B& bt = boost::get<B>(vec[1]); 

    if (at.state == bt.ref) { 
     std::cout << "SHOULD I EXPECTED THIS ?" << std::endl; 
    } 
    // the code doesn't print 
} 

지금, 나는 여기에 무슨 일이 일어나고 있는지 알고 싶은, 즉 그 위의 코드에 조건 평가가 거짓주는 경우 것으로 발생하는 어떤 ?

가능합니다.이 작업을 수행하는 방법에 대한 조언을 받고 싶습니다. 미리 감사드립니다.

+1

두 번째'push_back'는'에 전달 된 것을 포함하여, 벡터의 요소로 기존의 모든 참조를 무효화, 재 할당이 발생 B의 생성자. –

답변

1

문제는 두 번째 요소를 벡터에 추가 할 때 더 많은 메모리를 다시 할당하고 첫 번째 개체를 새 위치로 옮기고 참조가 끊어지는 문제입니다. 간단한 솔루션은 재 할당을 방지하거나 객체를 이동시키지 않는 다른 컨테이너를 사용하기 위해 사전에 std::vector에 충분한 메모리를 예약하는 것입니다. 그러나 원래의 솔루션에는 설계상의 결함이 있습니다. 오브젝트의 참조가 남아 있어야한다는 사실에 의존합니다. 그러나 귀하의 논리가 그것을 보장 할 수는 없으므로 std::vector에서 볼 수있는 문제가됩니다. 첫 번째 예제에서 b 오브젝트가 어쨌든 오브젝트 a보다 오래 지속되는 경우 동일한 문제점이있을 수 있습니다. 더 나은 해결책은 스마트 포인터를 사용하고 B 유형의 객체가 A 유형의 객체에 대한 공유 또는 약한 포인터를 보유하도록하고 소유하려는 소유권에 따라 다릅니다. 이 방법 당신은 std::vector에 포인터를 공유하고 메모리 재 할당은 영향을 미치지 않을 것이다 :

struct A { 

    A() : state(0) { } 
    A(int state_arg) 
     : state{ state_arg } { } 

    int state; 
}; 
typedef std::shared_ptr<A> APtr; 

struct B { 

    B(int state_arg, const APtr& ptr) 
     : state{ state_arg }, aptr{ ptr } { } 

    int state; 
    APtr aptr; 
    int ref() const { return aptr->state; } 
} 
typedef std::shared_ptr<B> BPtr; 

using my_type = boost::variant<APtr, BPtr>;