【问题标题】:Sorting vector of custom type by their constant id按常量 id 对自定义类型的向量进行排序
【发布时间】:2015-11-03 09:32:18
【问题描述】:

我需要按 Blah 的整数 id 对自定义类型 std::vector<Blah> v 的向量进行排序。我通过std::sort(v.begin(), v.end()) 执行此操作,运算符<Blah 中被重载为

bool operator< (const Blah& b) const { return (id < b.id); }

我注意到 Blah 的私有 id 不能声明为 const int id,否则 Blah 类型不符合 std::sort 的要求(我假设它与不可 ValueSwappable 冲突?)

如果 id 不是 const 一切都很好。但是,我不喜欢对象没有常量 id 只是为了在向量中重新排列它们的顺序的想法。

有没有办法,或者是这样吗?

【问题讨论】:

  • Id id 应该是唯一的吗?如果没有,您可以简单地确保除了赋值运算符之外的任何内容都不会导致 Blah 对象的 id 被修改。
  • 是的,实际上id 需要是唯一的。
  • 我在做一个疯狂的猜测:你想在 id 之后排序以便能够按 id 访问元素。为此,地图会更合适。
  • @IorisN:地图是非常有用的数据结构。确实,排序的向量有时(通常?)更快,但在您真正看到需要性能之前使用映射 - 映射更方便。
  • 是的,您可能可以在谷歌上搜索一些关于 STL 向量和性能的好文章 - 一个原因是数组/向量具有良好的缓存局部性,这有时对性能有很大帮助。但是地图对于性能也非常有好处 - 例如,它们不需要像哈希表那样重新散列,因此性能在 100% 的时间里都是对数的。

标签: c++ sorting vector


【解决方案1】:

有没有办法,或者是这样吗?

我担心事情就是这样。如果你想对一个向量进行排序,原则上它是一个数组,那么你必须在交换元素时将它们分配

至少我是这么想的,其实你可以作弊一点。将你的对象包装成一个联合体:

template<typename T>
union ac {
 // actual object
 T thing;
 // assignment first destructs object, then copy
 // constructs a new inplace.
 ac & operator=(ac<T> const & other) {
  thing. ~T();
  new (& thing) T(other. thing);
 }
 // need to provide constructor, destructor, etc.
 ac(T && t) : thing (std:: forward<T>(t))
 {}
 ac(ac<T> const & other) : thing (other. thing) {}
 ~ac() {
  thing. ~T();
 }
 // if you need them, add move assignment and constructor
};

然后您可以实现(复制)赋值运算符以首先破坏当前对象,然后(复制)从提供的旧对象的位置构造一个新对象。

您还需要提供构造函数和析构函数,当然这仅适用于 C++11 及更高版本,因为以前的语言标准中对联合成员的限制。

这似乎工作得很好:Live demo.

但是,我认为您应该首先重新审视一些设计选择,例如如果常量 id 确实需要成为您的对象的一部分

【讨论】:

  • 这是一个有趣的结构。谢谢你的分享。虽然我不会使用它,但我接受你的回答,因为它确实回答了我的问题。
【解决方案2】:

有没有办法,或者是这样吗?

所以你想更新/交换一个对象的全部数据(包括它的身份)并保持身份不变;两者是冲突的,因为 constant 意味着“不改变”(而 swap 意味着“改变这些实例”)。

您在这里偶然发现了 const-ness 的两个(相互竞争的)定义:概念 const-ness(数据所说/含义相同)和二进制 const-ness(表示数据的字节不变)。 (第一个定义导致在语言中引入 mutable:在打破二进制 const-ness 的同时保持概念上的 const-ness 的能力。

您的数据在概念上是常量(数据的接口应该是常量)但不是二进制常量(您可以交换值,因此您的位可能会转移到另一个实例)。

对此的规范想法是在内部保持数据非 const,并仅为客户端代码提供 const 公共/受保护的访问权限

你说:

但是,我不喜欢对象没有恒定 id 的想法,只是为了在向量中重新排列它们的顺序。

仅仅因为身份在概念上是恒定的(公开的 API 是/应该是恒定的),您没有实际的硬性要求来保持数据恒定(并且应该没有偏好,基于 API)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多