【问题标题】:Why/when should we prefer using std::swap; swap(a, b) over std::iter_swap(&a, &b)?为什么/何时我们更喜欢使用 std::swap;在 std::iter_swap(&a, &b) 上交换(a,b)?
【发布时间】:2015-05-18 00:08:30
【问题描述】:

为什么/什么时候我们应该更喜欢 using std::swap; swap(a, b); 而不是 std::iter_swap(&a, &b)

【问题讨论】:

  • @T.C.:哈哈,很公平,但还有其他情况吗? (但请随时将其发布为答案...)
  • 我认为您应该几乎总是“更喜欢”它以提高可读性
  • 你能把你的问题放在你的问题中吗,很难解析“using”是关键字 using,而不是实际单词
  • 两年前你也几乎没有问过这个问题吗? stackoverflow.com/questions/14024228/…
  • @Mehrdad。好吧,在我写完评论之后,我开始有了第二个想法。额外的 using 语句本身并不明显,所以我的评论可能只是反映了我自己的经验的偏见。

标签: c++ algorithm swap argument-dependent-lookup


【解决方案1】:

由于它们完全不同,因此您的问题是错误的二分法。

他们做不同的事情!

  • 一个交换值。
  • 另一个交换迭代器目标的内容。

但是如果你有迭代器。使用std::iter_swap 可能会更好。否则你可以使用交换(只要你在本地完成了using std::swap; 对交换的调用(否则正确交换的类型相关锁定可能会失败)。

std::iter_swap(i1, i2);

// Is equivelent to writing.
using std::swap;  // Notice this. 
swap(*i1 ,*i2);   // Notice the * in front of the iterator.

【讨论】:

  • 不,据我所知,他们不能做不同的事情(除非& 过载);该标准要求后者必须具有与前者相同的效果。
  • @Mehrdad:他们肯定做完全不同的事情。
  • 您能举例说明依赖类型的查找何时会失败吗?不,他们不能做不同的事情……你能举个例子说明他们什么时候做不同的事情吗?
  • @Mehrdad:阅读我的回答。一个尊重迭代器,另一个不尊重迭代器。你还想要多少不同。
  • 您确定您仔细阅读了我的问题吗?您答案中的代码与我询问的代码不同。
【解决方案2】:

通常,标准要求

std::iter_swap(&a, &b);

效果等同于

using std::swap;
swap(*(&a), *(&b));

而它可能以不同的方式实现。 (至少 g++ 和 msvc 只是交换...)

知道了,我会考虑

using std::swap;
swap(a, b);

更具体、更直接、更易读,因为它直接表达了所需的、支持 adl 的行为。

如果你一开始就有迭代器,那么我会坚持使用启用 ADL 的 iter_swap

using std::iter_swap;
iter_swap(it_a, it_b);

这里的原因是我有两次机会超越(或智取)默认std::swap

  1. 迭代器来自的容器的实现者可能为这些迭代器提供了iter_swap 的重载,这比普通值交换更智能(甚至可能更合适1)。
  2. 迭代器引用的类的实现者可能提供了swap 重载来有效地交换两个元素。

如果 (1) 不是这种情况,我可能会得到 (2) 并且仅当两个选项都不适用时,使用 std::swap 并移动(或在不可移动类型的情况下复制)对象以交换它们.

请注意,使用 iter_swap 的标准算法不会启用调用。

1可能适用于不直接表示对象(即 zip 范围)的特殊迭代器(范围)。

【讨论】:

  • 如果不实际调用swap,就没有实际有用的方法来实现swap 的效果......这就是为什么它最终成为多余和未使用的原因。
  • @Mehrdad:实际上,我们还缺少像 iter_move 这样的东西,以使 iter_swap 成为一个非常有用的自定义点,但也可以这样使用。
【解决方案3】:

3 年后,但我相信唯一的技术问题是 operator &() 是否过载。
如果不是,我看到的唯一其他原因就是可读性。

【讨论】:

    【解决方案4】:

    来自http://en.cppreference.com/w/cpp/algorithm/iter_swap

    可能的实施

    template<class ForwardIt1, class ForwardIt2>
    void iter_swap(ForwardIt1 a, ForwardIt2 b)
    {
       using std::swap;
       swap(*a, *b);
    }
    

    我认为

    using std::swap;
    swap(a,b);
    

    优于

    using std::iter_swap;
    iter_swap(&a, &b);
    

    第一个涉及更少的打字和更多的重点。

    【讨论】:

    • 对于任何特定用例都错了吗?
    • 你需要使用参数依赖查找,否则它不会通过ADL查找任何用户定义的swap
    • @Mehrdad,我需要深入挖掘。这对我来说并不明显。
    • @Barry: std::swap(a,b); 绝对使用 ADL。 (你看对了吗?)
    • @R Sahu:是的,不是很明显,但是using std::swap; swap(a, b); 不等同于std::swap(a, b);
    猜你喜欢
    • 1970-01-01
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    • 2016-05-24
    • 1970-01-01
    • 2020-09-21
    • 2021-09-10
    • 1970-01-01
    相关资源
    最近更新 更多