5

連想コンテナに関する SGI のドキュメントによると、「要素はキーに従って格納されるため、各要素に関連付けられたキーは不変であることが不可欠です」。ポインターを std::map へのキーとして使用することがあります。これは、ポイントされたオブジェクトが変更可能である可能性がありますが、ポインター自体は定数であるためです。

QPointer は技術的にはポインターを模倣したオブジェクトであり、Qt のドキュメントには、QPointer をポインターとまったく同じように使用できると書かれています。QPointer オブジェクト自体は実行中に変更される可能性があるため、std::map コンテナーのキーとして引き続き使用できますか?

編集 1: QMap を使用できません。std::map に固執する必要があります。
編集 2: QPointer を使用すると、コードがコンパイルされます。問題は、実行時に不愉快な驚きを期待すべきかどうかです。

4

3 に答える 3

7

いいえ、これは安全ではありません。 aが破棄されたときにQPointer<T>変更される可能性があるためです。(は に似ています。) したがって、このコードは未定義の動作を生成します。NULLQObjectQPointerstd::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!
于 2011-03-08T22:12:30.497 に答える
0

異なる割り当てブロックからのポインターを比較して、等値/不等値以外のものを比較することは、未定義の動作です。つまり、new または malloc でブロックを割り当てた後、バッファをウォークスルーして、ポインタがバッファの末尾よりも小さいかどうかをテストできます。ただし、2 つの別個のニュース/malloc を実行して、結果のポインターを等号/不等号以外のものと比較することはできません。

ええと...できますが、結果が気に入らない場合があります。

于 2011-03-08T21:34:18.967 に答える
0

QPointer再割り当てせず、基になるオブジェクトを削除しない場合、 aが指している場所を「魔法のように」変更しないので、安全であるはずです。

(Qt が最小の驚きの原則に違反しているのを何度か見たことを付け加えなければならないので、念のためにテストしてください。)

于 2011-03-08T21:23:19.617 に答える