2011-03-08 6 views
4

SGI's doc on associative containers에 따르면, "요소는 키에 따라 저장되므로 각 요소와 관련된 키는 변경 불가능합니다". 때때로 포인터를 std :: map의 키로 사용합니다. 포인터가있는 객체가 변경 될 수는 있지만 포인터 자체는 일정하기 때문입니다.QPointer를 std :: map의 키로 사용할 수 있습니까

QPointer는 기술적으로 포인터를 모방 한 개체이며 Qt's doc은 포인터와 똑같은 QPointers를 사용할 수 있다고 말합니다. QPointer 객체 자체는 실행 중에 변경 될 수 있기 때문에 std :: map 컨테이너의 키로 사용할 수 있습니까?

편집 1 : QMap을 사용할 수 없으며 std :: map을 사용해야합니다.
편집 2 : QPointer를 사용할 때 코드가 컴파일됩니다. 문제는 런타임에 불쾌한 놀라움을 기대해야하는지에 관한 것입니다.

+0

관련 : [? 주문 STL 컨테이너의 키로서 허용 포인터가 있습니까 (http://stackoverflow.com/questions/4913161/) –

답변

6

QObject이 파괴되면 QPointer<T>NULL으로 변경 될 수 있기 때문에 이것은 안전하지 않습니다. (. QPointerstd::weak_ptr과 유사) 그래서이 코드가 정의되지 않은 동작을 생산하는 것입니다 :

class CopyableWidget : public QWidget { 
    Q_OBJECT; 
public: 
    CopyableWidget(Widget* parent = 0) : QWidget(parent) {} 
    CopyableWidget(const CopyableWidget& w, Widget* parent = 0) : QWidget(parent) {} 
}; 

std::vector<CopyableWidget> v(2); // Two default-constructed widgets 
std::map<QPointer<CopyableWidget>, int> wid_values; 
wid_values[&v[0]] = 1; 
wid_values[&v[1]] = 2; 
// wid_values contains { {&v[0], 1}, {&v[1], 2} } 
v.resize(1); 
// The QPointer in wid_values constructed from &v[1] now acts like NULL. 
// wid_values contains { {&v[0], 1}, {NULL, 2} } 
// But &v[0] > NULL (on most platforms). Class invariant was violated! 
0

QPointer은 재 지정하지 않고 기본 객체를 삭제하지 않으면 "마술처럼"변경되지 않으므로 안전해야합니다 (최소한 놀라움의 원칙에 따라).

(내가 Qt는 적어도 놀라운 몇 차례의 원칙을 위반 보았으므로 추가, 그래서 확인하기 위해 테스트해야합니다.)

+1

Qt는 opensource입니다. 테스트하지 말고 코드를 살펴보십시오. – BatchyX

0

그것은 평등 이외의 서로 다른 할당 블록에서 포인터를 비교하는 정의되지 않은 동작입니다 /불평등. 나는. new 또는 malloc을 사용하여 블록을 할당 한 후에는 버퍼를 거쳐 포인터가 버퍼의 끝보다 작 으면 테스트 할 수 있습니다. 그러나 두 개의 별도 뉴스/malloc을 수행하고 결과 포인터를 평등/불평등 이외의 것으로 비교할 수는 없습니다.

음 ... 결과는 좋지만 좋지 않을 수 있습니다.

+1

그러나 연관 컨테이너는 모든 포인터 유형에서 작동하도록 정의 된'std :: less'를 사용합니다. –

+0

아마도 내가 사용중인 의사가 구식 인 것 같습니다. 필자는 포인터 사이의 관계 연산자가 같은 할당 내를 가리 키지 않는 한 불특정 행동을한다고 말하는 표준 섹션을보고 있습니다. 더 이상 사실이 아닌가? – Brad

+2

연관 컨테이너는 관계 연산자를 사용하지 않고'std :: less'를 사용합니다. 이것은 관계 연산자가없는 경우에도 포인터에 대한 전체 정렬을 제공하도록 특별히 정의됩니다. –

관련 문제