5

根据SGI 关于关联容器的文档,“由于元素是根据其键存储的,因此与每个元素关联的键必须是不可变的”。我有时使用指针作为 std::map 的键,因为尽管指向的对象可能是可变的,但指针本身是恒定的。

QPointer 在技术上是一个模仿指针的对象,Qt 的文档说我们可以像使用指针一样使用 QPointers。由于 QPointer 对象本身在执行过程中可能会发生变化,它仍然可以用作 std::map 容器的键吗?

编辑 1:我不能使用 QMap,我必须坚持使用 std::map。
编辑 2:当我使用 QPointer 时代码编译。问题是我是否应该在运行时期待不愉快的惊喜。

4

3 回答 3

7

不,这不安全,因为QPointer<T>可能会NULL在 aQObject被销毁时更改。(QPointer类似于std::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

我认为(从最不意外的原则)QPointer如果你不重新分配它并且不删除底层对象,它不会“神奇地”改变它指向的位置,所以它应该是安全的。

(我必须补充一点,我已经多次看到 Qt 违反了最少意外原则,因此请务必进行测试。)

于 2011-03-08T21:23:19.617 回答
0

比较来自不同分配块的指针以获取除相等/不相等之外的任何内容是未定义的行为。即在使用 new 或 malloc 分配块后,您可以遍历缓冲区并测试您的指针是否小于缓冲区的末尾。但是你不能做两个单独的新闻/mallocs 并比较结果指针以获取除相等/不等之外的任何内容。

嗯......你可以,但你可能不喜欢结果。

于 2011-03-08T21:34:18.967 回答