2017-05-15 3 views
1

내 질문은 다음 패턴과 관련이 있습니다. 다음 패턴을 사용하여 SomeData을 구성하는 데 비용이 많이 드는 것을 만들고 싶습니다. UsesData으로 이동하십시오. std :: vector, std :: move 및 포인터 무효화

그래서 질문은

...

은 여전히 ​​유효 보장 ud.dat.m_ptrs에서 포인터가 있습니까?

struct BigObject{}; 
struct SomeData 
{ 
    SomeData() = default; 

    SomeData(const SomeData &) = delete; 
    SomeData & operator = (const SomeData &) = delete; 

    SomeData(SomeData &&) = default; 
    SomeData & operator = (SomeData &&) = default; 

    std::vector<BigObject> m_data1; // big vector 
    std::vector<BigObject> m_data2; // big vector 

    // (m_ptrs.size() == m_data1.size() + m_data2.size()) 
    // points to elements in m_data1 and m_data2... 
    std::vector<const BigObject * const> m_ptrs; 
}; 

struct Builder 
{ 
    Builder() = delete; 
    Builder(const Builder &) = delete; 
    Builder & operator=(const Builder &) = delete; 
    Builder(Builder &&) = delete; 
    Builder & operator=(Builder &&) = delete; 

    Builder(int a) 
    { 
     // makes sure BigObject vectors in SomeDate are constructed correctly 
     // builds m_ptrs... vector of ptrs to m_data1 and m_data2 
    } 

    SomeData dat; 
}; 

struct UsesData 
{ 
    UsesData() = delete; 
    UsesData(const UsesData &) = delete; 
    UsesData & operator=(const UsesData &) = delete; 
    UsesData(UsesData &&) = delete; 
    UsesData & operator=(UsesData &&) = delete; 

    UsesData(Builder && from) : dat{ std::move(from.dat) } 
    {} 

    const SomeData dat; 
}; 

int main() 
{ 
    UsesData ud{ Builder{ 1 } }; 
    //... 
} 

답변

2

포인터는 유효합니다. move constructorstd::vector의 동작에 따르면

다른 유효하지만 요소를 참조하는 컨테이너 이동 구조 (과부하 (6)), 참조 포인터 및 (단 반복자 이외) 반복자 후 현재는 *this입니다. 현재 표준은 23.2.1 [container.requirements.general]/12에있는 담요 명세서를 통해이를 보장하며,보다 직접적인 보증은 LWG 2321을 통해 고려 중입니다.

즉, 이동 한 후에 포인터는 유효하고 새로운 std::vector으로 이동 된 요소를 가리 킵니다.

+0

주요 컴파일러가이 문제에 완전히 불만을 나타내고 있는지 알려지지 않았습니까? – Quantifeye

+0

@Quantifeye 모든 컴파일러에서 확인하지 않고 말하기는 어렵습니다. 내 경험에 따르면 gcc/clang은 적어도 괜찮을 것입니다. – songyuanyao

관련 문제