在向量之间使用std::swap还是vector::swap?

7

给定两个std::vector v1和v2。
我想知道使用std::swap(v1, v2)与v1.swap(v2)相比的好处。

我已经编写了一个简单的测试代码(我不确定它是否相关),涉及性能方面的问题:

#include <iostream>
#include <vector>
#include <random>
#include <chrono>
#include <algorithm>

#define N 100000

template<typename TimeT = std::chrono::microseconds>
struct Timer
{
    template<typename F, typename ...Args>
    static typename TimeT::rep exec(F func, Args&&... args)
    {
        auto start = std::chrono::steady_clock::now();
        func(std::forward<Args>(args)...);
        auto duration = std::chrono::duration_cast<TimeT>(std::chrono::steady_clock::now() - start);
        return duration.count();
    }
};

void test_std_swap(std::vector<double>& v1, std::vector<double>& v2)
{
    for (int i = 0; i < N; i ++)
    {
        std::swap(v1,v2);
        std::swap(v2,v1);
    }
}

void test_swap_vector(std::vector<double>& v1, std::vector<double>& v2)
{
    for (int i = 0; i < N; i ++)
    {
        v1.swap(v2);
        v2.swap(v1);
    }
}

int main()
{
    std::vector<double> A(1000);
    std::generate( A.begin(), A.end(), [&]() { return std::rand(); } );
    std::vector<double> B(1000);
    std::generate( B.begin(), B.end(), [&]() { return std::rand(); } );
    std::cout << Timer<>::exec<void(std::vector<double>& v1, std::vector<double>& v2)>(test_std_swap, A, B) << std::endl;
    std::cout << Timer<>::exec<void(std::vector<double>& v1, std::vector<double>& v2)>(test_swap_vector, A, B)  << std::endl;
    std::cout << Timer<>::exec<void(std::vector<double>& v1, std::vector<double>& v2)>(test_std_swap, A, B) << std::endl;
    std::cout << Timer<>::exec<void(std::vector<double>& v1, std::vector<double>& v2)>(test_swap_vector, A, B)  << std::endl;
}

根据输出结果显示,在没有优化-O0的情况下,vector::swap似乎更快。输出结果为(以微秒为单位):
20292
16246
16400
13898

使用-O3时,没有明显的差异。

752
752
752
760

除了普遍性之外。 - Benjamin Lindley
@DietmarKühl 是的,完全正确。我的意思是“重载”,但现在编辑我的第一条评论已经太晚了。 - juanchopanza
3个回答

11

假设实现合理,这两个函数应该被实现为相同的。因此,您应该在代码中使用最易读的函数。

特别地,如果我们看一下std::swap(vector<T> & x, vector<T> & y)的描述,它的作用是x.swap(y)


7

您在任何情况下都不应直接使用 std::swap()!相反,您应该使用类似以下的内容:

using std::swap;
swap(x, y);

对于std::vector<...>来说,它显然生存在命名空间std中,因此使用std::swap()或上述ADL方法并没有区别。否则,使用std::swap()将使用默认实现,而ADL方法可以找到更好的版本。
对于std::vector<...>类型的xy,使用swap(x, y)只是调用了x.swap(y)。为了保持一致性,建议使用上述ADL方法。
参考资料:

谢谢您的建议。这是为什么在上述示例中,std::swap没有优化时似乎更慢的原因吗? - coincoin
4
在没有优化的情况下,对C++代码进行分析是徒劳无益的!例如,对于所有可以轻松内联的东西都进行函数调用会增加显着的成本。由于生产代码肯定总是使用了优化,因此未经优化的代码的性能也是无关紧要的。 - Dietmar Kühl
1
因为问题的实际答案只在最后一段中,其余部分基本上是对代码风格的评论,所以被踩了。此外,我不同意第一部分,我会说只有在真正必要的情况下才使用 "using",在这种情况下并不必要。 - RobinP
@DietmarKühl 您的评论并不准确,我所有的性能分析都是在调试版本上进行的,我感兴趣的是优化正在使用的算法,而不是删除一些对性能影响微不足道的函数调用。 - RobinP

1

从实施文档中:

void swap(vector& __x)

   *  This exchanges the elements between two vectors in constant time.
   *  (Three pointers, so it should be quite fast.)
   *  Note that the global std::swap() function is specialized such that
   *  std::swap(v1,v2) will feed to this function.

你可以看到,std::swap(v1,v2)只是调用了v1.swap(v2)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接