2011-09-14 2 views
2

다음 클래스를 고려하십시오.cast stl :: stl에 대한 포인터를 포함하는 벡터 :: constant 포인터가 들어있는 벡터

class SomeInfo 
{ 
private: 
    std::vector<someObj *> _myVector; 

public: 
    const std::vector<const someObj*>& getInfoVector() const 
    { 
     return _myVector; 
    } 
}; 

gcc 4.1.2로 컴파일하려고하면 다음 오류가 발생합니다.

error: invalid initialization of reference of type 
‘const std::vector<const someObj*, std::allocator<const someObj*> >&’ 
from expression of type 
‘const std::vector<someObj*, std::allocator<someObj*> > 

'someObj'앞에 'const' * ', 그런 다음 컴파일하지만, 포인터가 아닌 포인터를 가진 벡터를 반환하고 싶지 않습니다. 왜냐하면 그 객체가 참조하는 객체가 내 SomeInfo 클래스 외부에서 변경되는 것을 원하지 않기 때문입니다. 이 상황에서 당신은 무엇을 할 것입니까?

+1

왜 _myVector를 처음부터 상수 포인터 벡터로 만들지 않는 것이 좋을까요? – Ferruccio

+0

나중 단계에서 상수 포인터를 '삭제'해야하는 소멸자가 있기 때문에 언어에서 허용되는 것으로 알고 있지만 추악한 것으로 간주합니다! 내 관점에서 볼 때, const는 const이고 만져서는 안됩니다 ...이 벡터 멤버의 경우는 아니지만 const가 아니며 const 값을 지정하고 싶습니다. – pinpinokio

답변

3

이 상황에서 내가 수행하는 것은 vector (또는 그에 대한 참조)을 반환하는 것을 잊어 버리는 것입니다. 호출자는 변경할 수 없으므로 특정 컨테이너를 볼 필요가 없습니다. 다른 대답은 벡터를 const someObj* 인 것처럼 벡터를 참조 할 수없는 이유를 설명합니다. 그 문제에 대해 나중에 vector 대신 deque을 사용하도록 클래스를 변경하면 벡터에 대한 참조도 반환 할 수 없습니다. 발신자가 단지 요소에 액세스해야하기 때문에,의 그들에게 그것을 제공하자

const someObj *getInfoAt(size_t n) const { 
    return _myVector.at(n); 
} 

const_info_iterator getInfoBegin() const { 
    return _myVector.begin(); 
} 

const_info_iterator getInfoEnd() const { 
    return _myVector.end(); 
} 

size_t getInfoSize() const { 
    return _myVector.size(); 
} 

// plus anything else they need. 

const_info_iterator가 쓸 약간 짜증나 클래스에 대한 형식 정의입니다. 그것은 std::vector<someObj *>::const_iterator을 포장하고 operator*의 유형을 const-ify로 포장해야합니다. boost::transform_iterator이 유용 할 수도 있고 처음부터 쓰는 것이 나쁘지 않을 수도 있습니다. 하지만 양방향 반복기는 연산자 오버로드가 많이 필요합니다.

std::vector<const someObj*> mycopy(myinfo.getInfoBegin(), myinfo.getInfoEnd()); 

은 그들이 가질 수 없습니다 것은 지속적으로 반영하는 vector입니다 : 발신자가 정말 다음 내 인터페이스를 사용하여 const someObj*의 벡터를 원하는 경우

이제 그들은 쉽게 특정 순간에 스냅 샷을 얻을 수 있습니다 변경된 다른 유형의 다른 vector 어딘가에 - std::vector 그냥 그렇게하지 않습니다.

+0

고마워요, 스티브, 어쩌면 당신의 접근 방식이 제 필요에 가장 잘 맞을 수도 있습니다. 당신은 내 클래스의 사용자가 내가 그에게주는 데이터 구조를 변경할 수 없기 때문에 왜 전체 데이터 구조를 제공해야합니까?이 구조의 요소를 노출시킬 접근 자 세트를 사용하여 노출합니다. 목숨을 구해줘. – pinpinokio

0

std::vector<T*>std::vector<const T*>은 같은 유형이 아닙니다. 어떻게 쓸 수 있습니까?

std::vector<T*> obj(100); 
std::vector<const T*> & ref = obj; //error 

이것은 코드에서 수행 한 작업으로 잘못되었습니다. 한 유형의 참조를 만들어 다른 유형의 객체를 참조 할 수 있습니다.

그래서이 시도 :

std::vector<const someObj*> getInfoVector() const 
{ 
    return std::vector<const someObj*>(_myVector.begin(), _myVector.end()); 
} 

을 지금은 원래 벡터에서 포인터를 포함하는 일시적으로 벡터를 반환 있다고. 또한 반환 유형은 이 아니며참조이 아닙니다.

+0

궁금한데 왜 반환 값에'const'가 필요한가요? (사본을 반환하는 것은 실제에 대한 참조를 반환하는 것과 동일한 의미를 갖지 않습니다.) –

+0

@James : 예. 필요하지 않습니다. – Nawaz

+0

반환 값의 포인터에 대한 const는 해당 포인터가 가리키는 개체의 값을 변경할 수 없도록합니다. 감사합니다 Nawaz, 당신이 말하는 상황을 설명하지만 벡터의 복사본을 반환하면 프로그램이 너무 느려져서 감당할 수 없습니다 (속도는 응용 프로그램에서 매우 중요합니다). – pinpinokio

0

이 같은 getInfoVector를 작성할 수 : 더 나은에서

const someObj* SomeInfo::getSomeObjAt(const size_t& idx) const { 
    return this->_myVector.at(idx); 
} 

:

std::vector<const someObj*> getInfoVector() const 
{ 
    std::vector<const someObj*> obj; 
    std::copy(_myVector.begin(), _myVector.end(), std::back_inserter(obj)); 
    return obj; 
} 
다른 답변에 대한 대안으로
+0

그래,이 작동하지만, 다시 성능에 심각한 영향을 미칠 것입니다 ... 나는 내 벡터의 사용자에게 특별한 새로운 구조를주고 싶지 않아, 나는 단지 그로 어리석은 짓을하지 않도록하고 싶다. – pinpinokio

0

What would you do in this situation?

는, 여기에는 복사 또는 할당을 필요로하지 않는 간단한 방법입니다 많은 문맥들, 그냥 SomeInfo 이 아니고은 내부를 노출합니다.

+0

감사합니다, 저스틴,이 첫 번째 답변에 꽤 많이 보입니다 -> "데이터 구조에 대한 액세스를 제공하지 말고 그 요소 만" – pinpinokio

+0

아마도, 스티브 제시섭의 답변을 첫 번째로 말하고 있습니다. 분 (그의 대답은 모든 첫 번째 요점에 대한보다 상세한 설명입니다.) 두 번째 요지는 매우 중요했습니다. 좀 더 자세히 말하자면'SomeInfo'는 전형적으로'somObj'를 클라이언트에게 넘겨주는 것이 아니라'somObj'에서 작동하는 것이어야 함을 의미합니다. – justin