QPointer可以成为std :: map的关键

时间:2011-03-08 21:17:40

标签: c++ qt stl qpointer

根据SGI's doc on associative containers,“由于元素是根据其键存储的,因此与每个元素关联的键必须是不可变的”。我有时使用指针作为std :: map的键,因为虽然指向的对象可能是可变的,但指针本身是不变的。

QPointer在技术上是一个模仿指针的对象,而Qt's doc表示我们可以像指针一样使用QPointers。由于QPointer对象本身可能在执行期间发生变化,它是否仍可用作std :: map容器的键?

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

3 个答案:

答案 0 :(得分:6)

不,这不安全,因为当NULL被销毁时,QPointer<T>可能会更改为QObject。 (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!

答案 1 :(得分:0)

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

(我必须补充一点,我已经看过Qt多次违反最小惊喜的原则,所以要测试一下。)

答案 2 :(得分:0)

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

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

相关问题